Cover

Fun with CollectionViews

October 25, 2009
No Comments.

Url: http://wilderminds.blob.core.windows.net/downloads/CollectionViewF…

I’ve recently been looking at the PagedCollectionView class. For those who are not familiar with this class, it allows you to automatically show sections of a collection in a paged way (especially when paired with the PagerControl). There is a good example on MSDN here:

http://msdn.microsoft.com/en-us/library/system.windows.data.pagedcollectionview(VS.95).aspx

The PagedCollectionView class supports the ICollectionView interface that supports a number of features that are really useful for dealing with collections.  These include:

  • Sorting
  • Filtering
  • Grouping

To show this, I decided to start with a simple DataGrid.  I created the PagedCollectionView and wrapped my data collection in it like so (GameList is a simple collection of a Game class to show some data):

PagedCollectionView view = 
  new PagedCollectionView(new GameList());

Then when data binding, I simple do the binding directly to the view instead of the collection:

theGrid.ItemsSource = view;

Using the PagedCollectionView as a wrapper for your collection provides the functionality of sorting, grouping and filtering to your collection. Let’s start with sorting.

The ICollectionView interface has a SortDescriptions collection that is used to set the sort for the view. For example, to sort our collection by ReleaseDate then Name, we can add two SortDescription objects to the collection:

view.SortDescriptions.Clear();

view.SortDescriptions.Add(
  new SortDescription("ReleaseDate", 
                      ListSortDirection.Descending));

view.SortDescriptions.Add(
  new SortDescription("ProductName", 
                      ListSortDirection.Ascending));

In our DataGrid, both columns will mark themselves with the sort markers to indicate the search. You can reverse this if you need to detect the changes in sorting that happens when the user clicks on the columns to sort.  You can do this by registering for the CollectionChanged event and looking at the SortDescription collection:

view.CollectionChanged += view_CollectionChanged;

...

void view_CollectionChanged(object sender, 
  NotifyCollectionChangedEventArgs e)
{
  foreach (var s in view.SortDescriptions)
  {
    MessageBox.Show(
      string.Concat("Sorting is: ", 
                    s.PropertyName, 
                    " - ", 
                    s.Direction));
  }
}

The ICollectionView also exposes the ability to group items in the DataGrid. To add grouping, you simply need to add new GroupDescription objects to the view’s GroupDescription list. The only type of GroupDescription that is currently implemented is the PropertyGroupDescription which allows you to group by a property. For example, to group by the ReleaseDate I added a new PropertyGroupDescription like so:

view.GroupDescriptions.Add(
  new PropertyGroupDescription("ReleaseDate"));

In the DataGrid, these groups look like so:

Grouping

The last feature I love about the ICollectionView interface is the ability to do arbitrary filtering. The interface has a Filter property that takes a Predicate<object> object.  This way we can use a simple lambda to perform filtering.  For example, to only show the games that have Microsoft in the name, I just create a simple lambda like so:

view.Filter = g => 
  ((Game)g).Publisher.Contains("Microsoft");

Cool, huh?