Rockford Lhotka

 Tuesday, September 29, 2009

CSLA .NET version 3.8.0 alpha 3 is now available.

The primary focus of version 3.8 is to enable more seamless support for the MVVM design pattern in Silverlight and WPF. The alpha 3 release brings the features I’ve been implementing in Silverlight into WPF.

Also, the samples downloads now include my MVVM experimental applications. I suppose you can call these samples, but they are really the apps I’m using to try out different ideas – so they aren’t what I’d consider a “full sample”. Still, you can see how the various new features work, and how the MVVM features allow creation of at least a basic CRUD UI (with some navigation) with no code-behind any XAML.

Please note that version 3.8 requires System.Windows.Interactivity.dll to build. This assembly is installed with Expression Blend 3, or the Blend 3 SDK. You must install at least the SDK before you can build CSLA .NET 3.8.0.

The new features (now in Silverlight and WPF) include:

  • New ViewModelBase and ViewModel base classes to simplify the creation of view model types in your application. ViewModelBase provides protected methods to simplify interaction with business object types, and ViewModel is an example subclass that exposes public methods for use by InvokeMethod or Execute
  • CslaDataProvider enhancements to allow “chaining” of data providers (so a child data provider’s ObjectInstance property can be bound to a property from a parent data provider’s business object)
  • InvokeMethod enhancements to handle essentially any UI control event, and to invoke either data provider or view model methods, including passing parameter values from data bound sources in the UI. Additionally, InvokeMethod is now fully bindable which simplifies (but changes) the XAML needed to use the control
  • Execute trigger action, which is somewhat like InvokeMethod, but is an action used within a System.Windows.Interactivity trigger handler. The trigger action model imposes some limitations on data binding, so Execute isn’t quite as powerful as InvokeMethod, but it is more compatible with the Blend 3 designer model
  • PropertyStatus enhancements so you can bind your UI control’s properties to properties on PropertyStatus to control its visual state. This is instead of having PropertyStatus try to directly manipulate the visual state of the UI control. Additionally, PropertyStatus is now fully bindable which simplifies (but changes) the XAML needed to use the control
  • MobileFormatter now uses binary XML by default to help improve performance

Please give these new features a try and let me know your thoughts on the forum.

Tuesday, September 29, 2009 2:36:13 PM (Central Standard Time, UTC-06:00)  #    Disclaimer

Thanks to a tremendous amount of time and effort on the part of Sean Rhone there’s a new release of CSLA .NET VB available for download from the VB download page.

Thank you Sean!!

This VB version of the framework should now have full parity with CSLA .NET for Windows 3.6.3. There’s one slight difference with the async data portal to work around the lack of multi-line lambda expressions in VB 9 – hopefully we’ll be able to bring that code back into parity with C# when VB 10 is available.

I recommend using this VB version of the framework as an implementation reference, not for production. The official release of CSLA .NET for Windows is the C# implementation, which is currently at version 3.7.1. It is available from the download page.

Tuesday, September 29, 2009 12:32:15 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Monday, September 28, 2009

CSLA .NET 3.7.1 for Windows and Silverlight are now available for download.csla_logo1_32_r

Version 3.7.1 supports .NET 3.5 SP1 and Silverlight 3.

This is primarily a bug fix release to address some issues with 3.7.0. Please see the change logs for details about the changes.

If you are using CSLA .NET version 3.5 or higher I recommend you look at the 3.7.1 release, as this is the current version for use with .NET 3.5 SP1, Visual Studio 2008 and Silverlight 3.

Monday, September 28, 2009 1:04:14 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Sunday, September 13, 2009

I have put two new pre-releases online, and they are available on the download pages:

CSLA .NET 3.7.1 Beta 3 is near-stable. In fact it would have been a release, except for one change I just added that I feel needs a beta cycle.

The 3.7.1 release is primarily bug fixes for a few issues in 3.7.0.

The only new feature is some support for creating custom FieldInfo<T> subclasses, which requires creating PropertyInfo<T> subclasses. If you are doing this, the new 3.7.1 changes in Beta 3 may make your life much easier.

CSLA .NET 3.8.0 Alpha 2 shows my continuing work and thoughts around the new Silverlight 3 binding capabilties and MVVM support.

All the new changes in Alpha 2 are on the Silverlight side, and impact:

  • CslaDataProvider - where the ObjectInstance property is now bindable, so you can "chain" data provider controls in parent-child relationships. This means you can have a child region on a form that is bound to a CslaDataProvider that got its data from the child property of a parent CslaDataProvider.
  • ViewModelBase - a base class that provides protected members you can use to more easily create a ViewModel class for your CSLA .NET business objects. The approach taken is one that exposes the Model (your business object) as a Model property of the ViewModel object; this is the flavor of MVVM that works best with CSLA .NET.
    This does include a protected method to create/fetch the Model as requested in one of the recent MVVM threads on the CSLA .NET forum.
  • ViewModel - a subclass of ViewModelBase that exposes public members for use with InvokeMethod or Execute (see below) so the methods can be invoked directly by XAML. Warning: I may or may not keep this class, depending on your feedback, as I don't know if it is the best plan overall.
  • InvokeMethod - which has breaking changes, but now automatically binds to the current DataContext and does a whole bunch of other nice work on your behalf to invoke methods on a data provider or ViewModel.
  • Execute - a new event trigger action using the new Blend 3 SDK feature of event triggers. The Execute action is similar to InvokeMethod, but works within the new event trigger infrastructure.
  • PropertyStatus - which has breaking changes, and is now bindable using element binding, and binds to the business object property instead of using a string literal for the property name. It also now exposes properties so a UI control can bind to PropertyStatus, instead of having PropertyStatus directly alter the UI control - this offers major new flexibility in UI design.

If you are using SL3 and/or are at all interested in MVVM, please take a look at what I'm doing in 3.8 and provide feedback.

As always, my intent is not for CSLA .NET to become a UI framework. At the same time, I feel the need to fill in at least the most glaring holes in the UI layer to enable use of CSLA .NET - and this means providing a basic way for XAML to invoke ViewModel methods, and for validation/authorization rules to be expressed in a rich manner in the UI.

It should be the case that any MVVM UI framework will be compatible with viewmodel objects you create by subclassing ViewModelBase. If that's not true, I'd like to hear about the issues you run into. Since ViewModelBase exposes nearly all protected members (except for Model, IsBusy and Error, which are public), I expect that it will provide an incredibly flexible start point for creating viewmodel objects.

The ViewModel base class is an example of how ViewModelBase can be subclasses to create a base that works with a specific UI implementation - specifically InvokeMethod and/or Execute.

Assuming generally positive feedback on the changes I've made on the Silverlight side, I'll port the appropriate changes to the WPF side, and then release 3.8.

Sunday, September 13, 2009 11:22:15 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Wednesday, September 2, 2009

I keep plucking away at the MVVM ideas, trying to make sure CSLA .NET allows people to implement the pattern in a smooth manner.

But I keep fighting with UI stuff in the process…

My scenarios center around the ListBox, because I find it to be nicely problematic. And common. Most apps have lists of stuff, and users select n items from the list and then do something with the items. So single-select and multi-select ListBox scenarios, where actions are triggered by the selection changing, or when a button is clicked – this is my current problem domain. Pure UI stuff.

I updated my existing InvokeMethod component to solve these problems, with some challenges, but it works nicely to invoke a method on a ViewModel. I’ve also played with the EventTrigger concepts from Blend 3, creating an Execute trigger action that invokes a method on the ViewModel, but there are some serious limitations here.

One scenario is pretty easy – triggering an action from the SelectionChanged event of the ListBox itself. The InvokeMethod and Execute solutions can both be handled with zero code-behind – just XAML interacting with the ViewModel.

Single-select with InvokeMethod

With InvokeMethod it looks like this:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         Name="DataListBox"
         csla:InvokeMethod.Target="{Binding Source={StaticResource ListModel}}"
         csla:InvokeMethod.TriggerEvent="SelectionChanged"
         csla:InvokeMethod.MethodName="ShowItem"
         csla:InvokeMethod.MethodParameter="{Binding RelativeSource={RelativeSource Self}, Path=SelectedItem}" />

And the ViewModel has a ShowItem() method like this:

public void ShowItem(Data methodParameter)
{
  // process methodParameter
}

Very simple and easy, and I like it a lot – except that InvokeMethod is fairly verbose and isn’t supported by Blend. I do like that the selected item is passed into the method as a strongly typed parameter though.

Single-select with event trigger

Using the event trigger model (which is supported by Blend) the ListBox looks like this:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         SelectedItem="{Binding Path=SelectedData, Mode=TwoWay}"
         Name="DataListBox">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <csla:Execute MethodName="ShowItem2" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox>

Notice that the ListBox.SelectedItem property is now bound to the SelectedData ViewModel property:

public static readonly DependencyProperty SelectedDataProperty =
    DependencyProperty.Register("SelectedData", typeof(Data), typeof(DataListViewModel), new PropertyMetadata(null));
public Data SelectedData
{
  get { return (Data)GetValue(SelectedDataProperty); }
  set { SetValue(SelectedDataProperty, value); OnPropertyChanged("SelectedData"); }
}

And the ViewModel method looks like this:

public void ShowItem2(object sender, Csla.Silverlight.ExecuteEventArgs e)
{
  // process this.SelectedData
}

While this is supported by Blend, I dislike the fact that the command method (ShowItem2()) has an invisible side-effect in that it requires the SelectedData property to be set before it will work. No one could know this without looking at the code or at documentation, so the overall readability is reduced in my opinion.

However, both solutions end up with a ShowItem() method that has the strongly-typed selected item, and the XAML uses binding to interact with the ViewModel in a reasonably clean manner – so I think either way is perfectly acceptable.

Multi-select with InvokeMethod

The multi-select ListBox scenario requires a Button (or similar control). The user selects multiple items in the ListBox, then clicks the Button to trigger processing of those items.

This scenario is not nearly so nice. Partly this is because of the way the ListBox works I think (or binding). The problem is that the SelectedItems property of the ListBox returns an ObservableCollection<object>, and when a binding is established between SelectedItems and another property it gets a reference to a collection that is not the collection you ultimately want.

In other words, when the form loads, SelectedItems points to an empty collection, and anything bound to it gets connected to that collection. When items are later selected the SelectedItems property seems to end up pointing to a different collection, and the binding has no idea this happened. The binding is still pointing to the original empty collection.

This means the binding to SelectedItems must be refreshed at the time the event trigger occurs, such as the Button control’s Click event.

I made InvokeMethod take care of this, so when using InvokeMethod the ListBox looks like this:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         SelectionMode="Multiple"
         Name="DataListBox" />

And the Button looks like this:

<Button Content="Process items"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="ProcessItems"
        csla:InvokeMethod.MethodParameter="{Binding ElementName=DataListBox, Path=SelectedItems}"/>

And the ViewModel method looks like this:

public void ProcessItems(System.Collections.ObjectModel.ObservableCollection<object> methodParameter)
{
  // process methodParameter
}

This only works because InvokeMethod refreshes the binding of its MethodParameter property when it gets the Click event from the Button. If it just took the normal binding value, it would always return an empty collection…

But the fact is that InvokeMethod does make this work in a very smooth and easy manner, allowing the ViewModel to implement a method that accepts the list of selected items as a parameter.

Multi-select with event trigger

Using the trigger action approach things are really messy, because there’s no way to force a refresh of anything that is bound to SelectedItems.

Worse, you can’t actually bind SelectedItems on the ListBox itself like you bind SelectedItem. In other words, the ListBox ends up looking like this:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         SelectionMode="Multiple"
         Name="DataListBox">
</ListBox>

Where you’d want to bind SelectedItems to a property of the ViewModel, that’s not possible.

So I thought I’d use a bit of a hack and bind it to the Tag property of the Button:

<Button Content="Process items"
        Tag="{Binding ElementName=DataListBox, Path=SelectedItems}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <csla:Execute MethodName="ProcessItems2" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

While this “works”, it doesn’t really. The problem is that the binding is established when SelectedItems is an empty collection, and it never changes. So this is NOT a useful way to get the list of selected items.

In the end, the solution appears to be that the ViewModel must know that it is dealing with a ListBox so it can get the items directly in the command method. That means the Button must provide a link to the ListBox (via Tag):

<Button Content="Process items"
        Tag="{Binding ElementName=DataListBox}">

This way the command method can interact with the Tag property to get a reference to the ListBox to get at the SelectedItems collection:

public void ProcessItems2(object sender, Csla.Silverlight.ExecuteEventArgs e)
{
  var listBox = ((System.Windows.Controls.Control)e.TriggerSource).Tag as System.Windows.Controls.ListBox;
  var selection = listBox.SelectedItems;
  // process selection
}

This is bad because now the ViewModel must know details about the control in the View. It is directly using the ListBox type, which means that the XAML can’t be easily changed to use some other type of list-oriented UI control – at least not without coming back here and changing this code.

I guess one solution would be to create a custom Button subclass that refreshes the binding of its Tag property when the button is clicked – but that’s not a good general solution by any means…

So in the multi-select scenario InvokeMethod is a decent solution, but trigger actions really fall down and the solution seems very inadequate. I think this is primarily due to the implementation of ListBox.SelectedItems, but I also think it is safe to assume that other UI controls will have similarly ill-behaved properties that make trigger actions harder to use than they should be.

Wednesday, September 2, 2009 3:25:26 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, August 14, 2009

Based on my recent posts regarding Silverlight, MVVM and invoking methods on arbitrary target objects, a couple people suggested that behaviors or trigger actions might be a good solution.

These are new concepts introduced through the System.Windows.Interaction assembly that comes with Expression Blend 3. That’s somewhat of a drawback, since this means a developer is required to install Blend 3 to get the assembly before these features are available. It would be nicer if they were part of the standard Silverlight (and WPF) development platform.

The other challenge I’ve encountered in working with this technology is a limitation when it comes to data binding. Silverlight only full binds with dependency properties of FrameworkElement objects. Since classes like TriggerAction<T> don’t inherit from FrameworkElement, their dependency properties aren’t bindable. This means you can’t define a property on a trigger and then bind it to other elements in the UI, which is really an unfortunate limitation.

For example, I created an Execute trigger action that defines MethodName and MethodParameter properties. If I have a ListBox and a Button, and I want the Button to trigger some method that acts on the SelectedItem property of the ListBox, what I’d really like to do is this:

<Button Content="Refresh">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <csla:Execute MethodName="Load" MethodParameter="{Binding ElementName=MyListBox, Path=SelectedItem}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

(in this code the ‘i’ prefix refers to System.Windows.Interactivity from Blend 3 and the ‘csla’ prefix refers to Csla.Silverlight from CSLA .NET)

Unfortunately this won’t get past the Silverlight XAML parser, because a binding expression isn’t allowed for MethodParameter…

I also wanted to implement a MethodTarget property so the Execute trigger could invoke methods on some object other than the current DataContext. Unfortunately that puts us back to needed the ability to use binding to specify the value of MethodTarget, which isn’t possible. So my current implementation can only invoke methods on the DataContext of the associated control (the Button in this case).

To get around the MethodParameter limitation I’m using a Tag hack

<Button Content="Refresh" Tag="{Binding ElementName=NewIdTextBox, Path=Text}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <csla:Execute MethodName="Load" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

When the Execute trigger invokes the method, it passes an ExecuteEventArgs parameter to the method, which includes a TriggerSource property of type FrameworkElement. This means the method, in the view model class, can access the Tag property of the associated control (the Button), which can be bound because the Button is a FrameworkElement:

public void Load(object sender, ExecuteEventArgs e)
{
  var tag = e.TriggerSource.Tag.ToString();
  int id = 0;
  if (!string.IsNullOrEmpty(tag))
    id = int.Parse(tag);
  Load(id);
}

Sure this is somewhat hacky, but since the trigger action can’t define bindable properties of its own, this seems like a workable solution.

Friday, August 14, 2009 12:44:31 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Thursday, August 13, 2009

CSLA .NET 3.6 normally requires .NET 3.5 SP1. However, if you are using Visual Studio 2008 it is possible (with some work and a third party LINQ library) to get CSLA .NET 3.6 running on .NET 2.0 SP1. Jonny Bekkum has done just that, and has contributed the results of his efforts to the community - thank you Jonny!

The result is a large subset of version 3.6.3 that builds and runs on .NET 2.0 SP1, eliminating the need for .NET 3.5 SP1 (though adding the need for LINQbridge, a third-party component).

You get to use the most of the new features in CSLA .NET, including:

  1. Managed properties in BusinessBase, ReadOnlyBase and CommandBase that reduces the number of lines required to declare a property.
  2. PropertyInfo type for less hardcoding of property names in your code.
  3. FieldManager and DataPortal enhancements, including the asynchronous DataPortal and Child_XYZ mehthods.
  4. ObjectFactory for separation of BO and DAL
  5. CslaActionExtender reduces the amount of code behind required in Windows Forms
  6. Reflection enhancements (MethodCaller) for dynamic calls
  7. An easier upgrade path to CSLA .NET 3.7 and Silverlight
  8. and a lot more ….

Jonny has not only got the CSLA .NET framework running on .NET 2.0, but he’s got unit tests and samples! This is an amazing contribution to the community.

You can download this version from http://www.lhotka.net/cslanet/N2.aspx.

Thursday, August 13, 2009 10:33:45 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, August 7, 2009

Welcome to the August edition of our Webinar Schedule!
We are pleased to introduce a series of exciting new webinars! For the month of August, we offer webinars on what Metrics Every Performance Testing Engagement Should Provide to Ensure Application Stability and on how to use SharePoint for Extranets. In collaboration with the Chicago Technology Executives Club, we are offering Business Dashboards - Developing a Culture of Intelligent Execution with Magenic's Dan English. In September, we begin a 5-part series on Silverlight Application Migration with Rocky Lhotka, Corey Miller, and Anthony Handley. We will cover the topics, Why Silverlight?, Windows to Silverlight, Web to Silverlight, Reimagining the UI in SIlverlight, and Silverlight: Service-oriented vs. n-tier. We are excited for you to attend these educational, cutting-edge webinars from our experts!


Magenic Webinars are complimentary and are designed as a resource for IT decision makers. Learn from our experts and have your questions ready for the Q&A at the end of each presentation. Register now for these exciting webinars!



Thursday, August 20th, 11:00 PT, 1:00 CT, 2:00 ET
Do you know how your application will perform when you go live?  Performance Testing will simulate how your application will perform with real life scenarios, enabling you to find and fix performance issues prior to launch. This will enable you eliminate risk and potential system down time, such as your customers not being able to access your website. This presentation will help guide you through the initiation, planning, and execution phases of your Performance Testing Engagement.




Thursday, August 27th, 11:00 PT, 1:00 CT, 2:00 ET
SharePoint 2007 seems to be everywhere. This webinar will offer a perspective on the key issues involved in leveraging the SharePoint platform for Extranets. Topics will include an overview and common pitfalls related to: Security, Authentication & Authorization, Architecture, Search, and Content Management.


·

We are excited to introduce our 5-part Silverlight Application Migration series beginning in September. Rocky Lhotka, Corey Miller, and Anthony Handley will be presenting this series. Click the picture above for full descriptions of each webinar and registration for the entire series or the webinars of your choice.




Wednesday, August 26th, 10:00 PT, 12:00 CT, 1:00 ET
In the current economic climate, it is more important than ever for business stakeholders to have a pulse on what is happening in their organization. Implementing an Executive Dashboard allows an organization to more effectively and efficiently execute on strategy, improve business processes and manage key company metrics proactively. This webinar is presented by Magenic's Dan English in conjunction with the Chicago Technology Executives Club.

 


Magenic Delivery Center About Us Careers Events

 

 

Friday, August 7, 2009 12:20:00 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Tuesday, August 4, 2009

CSLA .NET 3.6 introduced the InvokeMethod component for Silverlight, which was intended to replace at least the basic WPF commanding functionality I tend to use to trigger actions on a CslaDataProvider when buttons are clicked. And it did that.

It turns out however, that with a few tweaks, InvokeMethod is much more broadly useful than just triggering actions on a CslaDataProvider. In a more general sense, InvokeMethod can be used to call a method on nearly any object in response to nearly any event being raised by a UI control.

I’ve been reworking InvokeMethod quite a bit over the past few days, and whatever I end up doing will be in CSLA .NET 3.8. And it will be a breaking change over the 3.6 and 3.7 functionality, which is unfortunate, but I think it is worth it.

This blog post is not the final word, just kind of a “state of the control” post to solicit thoughts and feedback as I work on version 3.8.

In the new model, InvokeMethod can still invoke methods on a CslaDataProvider, so no functionality is lost.

But in the new model, InvokeMethod can invoke methods on other arbitrary objects, as long as they can be described through a binding expression. In other words, any bindable object that has a method becomes a valid target. And the range of trigger events is much broader; in fact any event should now work, though I’ve only tested a handful of common events (click, doubleclick, selectionchanged, etc).

Using some data binding trickery I’ve made the Target property (used to be the Resource property) optional. If you don’t set the Target property, InvokeMethod will target the DataContext of the control to which it is attached. This is not so useful with a data provider model, but is very useful with a ViewModel model.

Simple scenario

So an example of triggering an action on a ViewModel when a button is clicked:

<Button Content="Refresh"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="Load" />

When the button is clicked a Load() method is invoked on the current DataContext, which is probably a ViewModel class with a Load() method:

public class DataListViewModel : CslaViewModel<DataList>
{
  public void Load()
  { 
  }
}

That’s the simplest example, and could be handled by commanding in WPF.

ListBox doubleclick scenario

A more interesting example is where the UI needs to do something in response to a doubleclick of an item in a ListBox. This is interesting because there’s a temporal issue where the user could select an item in the list, and not doubleclick on it ever, or for a long time. In my mind, the ViewModel would handle the doubleclick through a method that accepts the selected item as a parameter:

public void ProcessItem(Data item)
{
}

That implies that InvokeMethod can pass the selected item as a parameter, and in the current incarnation it can do this:

<ListBox
         ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         csla:InvokeMethod.TriggerEvent="MouseDoubleClick"
         csla:InvokeMethod.MethodName="ProcessItem"
         csla:InvokeMethod.MethodParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"/>

The ambient DataContext here is the ViewModel object, and you can see that the ListBox loads its items from the Model property (where the Model is a collection of Data objects). The only really interesting thing here is that the MethodParameter property is using binding to pick up the SelectedItem property from the UI control – so from the ListBox. This directly meets my requirement of being able to pass the selected item to the ViewModel method.

The ViewModel doesn’t care what type of UI control is used, as long as it gets a selected Data item. This also means the ViewModel is quite testable, because it is a simple method that accepts a strongly typed parameter.

MultiSelect ListBox scenario

This even works with a multiselect ListBox control (though my solution seems a bit messy).

Obviously this requires a Button or some other control outside the ListBox, since a multiselect ListBox doesn’t raise events quite the same way. The user gets to select arbitrary items in the ListBox, then click a Button to trigger processing of all selected items.

The ViewModel has a method to handle this:

public void ProcessItems(ObservableCollection<object> items)
{
}

And the XAML invokes this method from the Button (assuming the ListBox has an explicit name):

<Button Content="Process items"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="ProcessItems"
        csla:InvokeMethod.MethodParameter="{Binding ElementName=DataListBox, Path=SelectedItems}"/>

Again, the ViewModel just accepts a (relatively) strongly typed parameter, not caring about the type of UI control that generated that value. There’s no real type-level coupling between the XAML and the ViewModel.

In all these cases the XAML knows nothing more than that there’s a Model to bind to, and some actions (methods) on the ViewModel that can be invoked.

And the ViewModel knows nothing more than that it is being invoked by something. XAML, a test harness, it doesn’t really matter, it just does its thing.

Whether this is “MVVM” or not, I think it is pretty darn cool :)

Tuesday, August 4, 2009 9:30:44 PM (Central Standard Time, UTC-06:00)  #    Disclaimer

I’m trying to do something that seems like it should be so simple and obvious.

I have an attached property, MethodParameter, which I’m applying to a Button, but I’m binding to a ListBox control:

<Button Content="Process items"
        csla:InvokeMethod.TriggerEvent="Click"
        csla:InvokeMethod.MethodName="ProcessItems"
        csla:InvokeMethod.MethodParameter="{Binding ElementName=DataListBox, Path=SelectedItems}"/>

This works, and does bind. But it appears to bind only when the Button control is instantiated, not when the Click event is handled.

In other words, the binding occurs. The user then interacts with the ListBox control and selects some items, and then clicks the Button. That triggers the Click event, which causes the InvokeMethod object to actually use the MethodParameter value.

However, at that point in time the binding appears to still be using the original collection from when the form was being loaded, and so the collection is empty.

If I actually examine the SelectedItems property it has multiple items of course – but it is a different collection than the one from when the form was loaded.

In other words, ListBox seems to create a whole new collection each time SelectedItems is invoked, and that’s apparently totally messing up data binding.

I don’t know if this problem is unique to ListBox, or if it is a broader problem with element binding, but it is making my life very unpleasant…

To solve this, I’m hijacking the binding process like this:

public static object GetMethodParameter(UIElement ctrl)
{
  var fe = ctrl as FrameworkElement;
  if (fe != null)
  {
    var be = fe.GetBindingExpression(MethodParameterProperty);
    var dataItem = be.DataItem;
    string path = be.ParentBinding.Path.Path;
    if (dataItem != null && !string.IsNullOrEmpty(path))
    {
      var pi = Csla.Reflection.MethodCaller.GetProperty(dataItem.GetType(), path);
      return Csla.Reflection.MethodCaller.GetPropertyValue(dataItem, pi);
    }
  }
  return ctrl.GetValue(MethodParameterProperty);
}

Basically I’m using reflection to manually go get the property value of the target object. This works, but feels really wrong.

If we’re dealing with a nasty idiosyncrasy of the ListBox I can probably restrict this to only be messy when talking to a ListBox control, but I rather suspect ListBox isn’t the only issue.

I’ve tried all sorts of things on the binding expression - Mode=TwoWay and BindsDirectlyToSource=True. But they had no impact. It appears that the binding gets a reference to the property value when it is created and never knows enough to re-read the value later when I actually need it.

Any ideas?

Tuesday, August 4, 2009 9:13:49 PM (Central Standard Time, UTC-06:00)  #    Disclaimer