Wednesday, February 26, 2014

WPF CollectionViewSource and Live Shaping - WPF 4.5 & 4.0

Microsoft improved CollectionViewSource in WPF 4.5 to include Live Shaping. Live shaping is a modern idea in UI design which allows to re-evaluate the dependents when a dependee changes value. For WPF's CollectionViewSource, we can define sorting order by introducing SortDescriptions to it. We can add a list of properties to identify the sort order of the items in the collection. In the earlier versions, the position of an item in the sort order was determined when it is added or removed. But if the identified property changes value than it is not re-evaluated.

Live Shaping is similar to forward chaining mode of Inference Engine where rules (sort order) is re-evaluated based on other dependent rules (property changes). The feature has been added in .net framework 4.5 by including ICollectionViewLiveShaping interface.

This post is based on a funny story. While working on a client project, I realized that the live shaping is not working for a CollectionViewSource. Later I realized that they are on .net framework 4.0 and cannot upgrade version. But the business requirements suggested that the items must be re-sorted when an item changes value. Let's first start with an example in WPF 4.5 to see how Live Shaping works in the newer version. Then we will be trying to add a similar feature to 4.0 based CollectionViewSource.

Let's create a sample WPF application using .net framework 4.5. We name the project as WpfApp_LiveShaping.

Here we are updating MainWindow.xaml. The view is using a ListBox to show students data. Here we are concatenating First and Last names of students separated by a hyphen '-'. In order to hand over the sorting to WPF runtime, we are using CollectionViewSource here. We are FirstName property for sorting (ascending by default). Here IsLiveSortingRequested is being set to true. This would include live shaping for sorting. There are other properties including IsLiveGroupingRequested and IsLiveFilteringRequested for including the same for grouping and filtering respectively.

In the above view, we are using a local instance of MainViewModel as the DataContext. The view model is expected to have a Students collection. Each item in the collection is supposed to have FirstName and LastName properties.

And here is the StudentViewModel type used as items in the MainViewModel described above. As stated, it just has two properties FirstName and LastName.

Now in order to stick it in for MVVM police, we have a Click handler for the button in the view. It just changes one property in the view model from Vladimir to David. This should result in re-sorting and hence re-positioning of the item.

Now let's run the application. As we click the button in the bottom, the value of the last item changes and hence it is re-positioned in the list as follows:

What about WPF 4??
Now we need to see if we can achieve the same behavior in WPF 4. Actually there is no such support out of the box for this. Since the framework doesn't support so, we need to write custom code for this purpose. Let's extend CollectionViewSource to support Live sorting.

Here we are using OnSourceChanged member to hook up collection changed events on the source collection of the collection view. It is assumed that the source of the collection view is an INotifyCollectionChanged type. Now we just need to update the Resource section with this updated collection view source definition as follows:

The above code should incorporate live sorting in the above view for an earlier version of WPF. It should not be recommended for any version including and after 4.5.

Download Code: