Search code examples
wpfdata-bindingmvvm

How to set a filter for a DataGrid ItemSource via MVVM


I have a DataGrid bound to a CollectionViewSource in XAML.

<Window.Resources>
  <local:MainWindowViewModel x:Key="ViewModel"/>
  <CollectionViewSource x:Key="cvsEntries" 
                        Source="{Binding LogEntriesStore, 
                                 Source={StaticResource ViewModel}}"/>
</Window.Resources>

LogEntriesStore is an ObservableCollection (LogEntry is a DTO that's not important in this discussion)

The DataGrid is declared as:

<DataGrid AutoGenerateColumns="False" 
          Margin="0" 
          Name="dataGrid1" 
          ItemsSource="{Binding Source={StaticResource cvsEntries}}" 
          IsReadOnly="True">

Now I have context menus on various cells in this DataGrid, to kick off a request for filtering. Right click on a cell, and pick filter to filter all the rows, and show only this particular value.

The MVVM gets the request to filter, but the now the tricky bit. How do I set the filter on the CollectionViewSource?

(as an aside -- this would have been a walk in the park with a Silverlight PagedCollectionView but that doesn't seem to be available in WPF, is that right?)


Solution

  • Very simple. You just need to move the collection view inside the view model:

    1. In MainWindowViewModel define a property of type ICollectionView:

      public ICollectionView LogEntriesStoreView { get; private set; }
      
    2. Right after you have initialized the LogEntriesStore property, you need to initialize the LogEntriesStoreView property with the following code:

      LogEntriesStoreView = CollectionViewSource.GetDefaultView(LogEntriesStore);
      
    3. Then you need to remove the CollectionViewSource from XAML and modify the ItemsSource binding to point to the newly created collection view property:

      <DataGrid AutoGenerateColumns="False" 
                Margin="0" 
                Name="dataGrid1" 
                ItemsSource="{Binding LogEntriesStoreView, Source={StaticResource ViewModel}}" 
                IsReadOnly="True">
      

    That's it. Now you have the access to the collection view inside your view model, where you can modify the filter.