BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Data Binding - Collection Views - Filtering Data

The one hundred and fifth part of the Windows Presentation Foundation Fundamentals tutorial expands upon the previous article, which described collection views. This article manipulates collection views using C# code to apply sorting, grouping and filtering of the data.

Creating Collection Views in C#

To create a collection view, you must generate an object that implements ICollectionView and that is linked to the underlying collection. You don't need to create the object directly. Instead, you can use a static method from the CollectionViewSource class. The method is named, "GetDefaultView".

Whenever you bind to a collection using WPF, you actually bind to its default collection view. This view is obtained silently by WPF and normally includes no sorting, grouping or filtering. GetDefaultView returns a reference to the default view, which you can then manipulate to add these features.

Let's create two properties in the ProductData class to hold our views. These properties can be the target of our bindings.

public ICollectionView ProductsView { get; private set; }

public ICollectionView ProductOptionsView { get; private set; }

We can amend the ProductData class's constructor and add some private methods to set up the two views. To begin, we'll not change the visible data. We'll simply set the new properties to hold the default views for the two collections.

public ProductData(IList<Product> products, IList<ProductOption> options)
{
    Products = new ObservableCollection<Product>(products);
    ProductOptions = new ObservableCollection<ProductOption>(options);

    InitialiseViews();
}

private void InitialiseViews()
{
    InitialiseProductsView();
    InitialiseProductOptionsView();
}

private void InitialiseProductsView()
{
    ProductsView = CollectionViewSource.GetDefaultView(Products);
}

private void InitialiseProductOptionsView()
{
    ProductOptionsView = CollectionViewSource.GetDefaultView(ProductOptions);
}

Let's modify the bindings for the two ListBoxes to point to the collections views:

<TextBlock FontWeight="Bold" Foreground="White" FontSize="20">Products</TextBlock>
<ListBox Grid.Row="1" ItemsSource="{Binding ProductsView}" DisplayMemberPath="Name"/>

<TextBlock Grid.Column="1" FontWeight="Bold" Foreground="White"
            FontSize="20">Options</TextBlock>
<ListBox Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ProductOptionsView}"
            DisplayMemberPath="Option"/>

Run the program to see the results. You'll find that the displayed lists are unchanged.

Adding Sorting and Grouping

When we added sorting and grouping in XAML, we created a CollectionViewSource proxy and set the SortDescriptions and GroupDescriptions attributes. When performing the same functions using C#, you can add SortDescription objects to the SortDescriptions property of the collection view, or add PropertyGroupDescription objects to the GroupDescriptions collection. For both types you can set the controlling property by passing a string containing its name to the constructor.

Modify the two initialisation methods, as shown below, to add grouping and sorting. The product list is grouped by its Group property. Each group is then sorted by name. The product options list is sorted by the Option property.

private void InitialiseProductsView()
{
    ProductsView = CollectionViewSource.GetDefaultView(Products);
    ProductsView.GroupDescriptions.Add(new PropertyGroupDescription("Group"));
    ProductsView.SortDescriptions.Add(
        new SortDescription("Name", ListSortDirection.Ascending));
}

private void InitialiseProductOptionsView()
{
    ProductOptionsView = CollectionViewSource.GetDefaultView(ProductOptions);
    ProductOptionsView.SortDescriptions.Add(
        new SortDescription("Option", ListSortDirection.Ascending));
}

To show the group details, modify the ListBox to add a data template to the group style:

<ListBox Grid.Row="1" ItemsSource="{Binding Products}"
            DisplayMemberPath="Name">
    <ListBox.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Foreground="DarkGreen" Text="{Binding Name}"
                               FontStyle="Italic"/>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ListBox.GroupStyle>
</ListBox>

The resultant window appears as shown below:

WPF CollectionView sorting and grouping in code

19 October 2014