XAML Playground
about XAML and other Amenities

Use CollectionViewSource effectively in MVVM applications

2009-07-18T23:13:15+01:00 by Andrea Boschin

In a my I've outlined the new CollectionViewSource introduced in silverlight with the latest release. This control is really useful while we need to sort and filter collection of objects in memory, but if we need to use a Model-View-ViewModel pattern to develop our application there is some problems using the control.

To implement the MVVM pattern we need to inject a ViewModel into the View using the DataContext property. This is usual in this kind of application because we need to bind the properties of the ViewModel to the controls in the View. So if we need to use a CollectionViewSource we can try to bind a collection from the ViewModel to the CVS and then bind the control to the CVS itself. Unfortunately this approach does not work because we cannot bind the CVS directly to the DataContext of the page. Trying to do this operation we will get a AG_E_BAD_PROPERTY_VALUE exception because the control does not inherits from FrameworkElement so it does not support DataBinding.

However, if it were possible, the CollectionViewSource would force us to put a lot of code in the codebehind to handle the Filter event and the sorting property. So, we have to follow another way to use the CollectionViewSource effectively with this kind of applications.

How to use the CollectionViewSource

The only way to use the CollectionViewSource with the MVVP pattern is to expose it as the type of the bindable property. This way we can manage the properties of the CVS and handle the Filter event from inside the ViewModel without putting anything in the codebehind of the View.

First of all we have to create two properties in the ViewModel. The first property will be the ObservableCollection<T> and we will populate it with the data to display. This property can be private because it will be used only to feed the ColectionViewSource of the second property. Here is how to initialize the properties:

   1: /// <summary>
   2: /// Gets or sets the names.
   3: /// </summary>
   4: /// <value>The names.</value>
   5: public CollectionViewSource Names { get; set; }
   6:  
   7: /// <summary>
   8: /// Gets or sets the names internal.
   9: /// </summary>
  10: /// <value>The names internal.</value>
  11: private ObservableCollection<string> NamesInternal { get; set; }
  12:  
  13: /// <summary>
  14: /// Initializes a new instance of the <see cref="MainPageViewModel"/> class.
  15: /// </summary>
  16: public MainPageViewModel()
  17: {
  18:     this.NamesInternal = new ObservableCollection<string>();
  19:     this.Names = new CollectionViewSource();
  20:     this.Names.Source = this.NamesInternal;
  21:  
  22:     // populate the ObservableCollection
  23:     foreach (string item in DataSource.GetNames())
  24:         this.NamesInternal.Add(item);
  25: }

Now, to bind the CollectionViewSource in the XAML we have to rely on his View property. If we put a reference to the CVS in the property ItemsSource in the XAML it simply will not work. Here is how to correctly bind:

   1: <ListBox ItemsSource="{Binding Names.View}" Margin="5,5,5,1" Grid.ColumnSpan="4" />

Once we have connected the CVS to the collection and the UI to the CVS we can handle the commands from the View and interact with the CVS to modify how to display the data. In the sample I have a togglebutton that is raising a ChangeSortDirectionCommand. I use the DelegateCommand<T> from Prism V2.0 and when someone send the command I change the SortDescriptor in the CollectionViewSource.

In the same View the TextChanged event is raised when the user type in the textbox. This command handled by the ViewModel let the CVS refresh itself. This way the Filter event will be evaluated again and the View will be updated with the filter applied.

I've attached to the post a new version of the sample I've proposed with the first article. Now the sample use the MVVM pattern with the CollectionViewSource.

Download: Elite.Silverlight3.CollectionViewMVVM.zip (~520 KB)

Categories:   Prism | Databinding | Prism
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

Comments (1) -

July 24. 2009 06:09

Nice post.

I wrote two blog posts about using the collectionviewsource in a viewmodel.
Maybe you find it interesting.
http://reyntjes.blogspot.com/2009/06/viewmodel-for-observablecollection.html
and
http://reyntjes.blogspot.com/2009/04/master-detail-viewmodel_24.html

Robert

Robert

Pingbacks and trackbacks (1)+