Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?)

like image 961
Ralph Shillington Avatar asked Apr 27 '11 20:04

Ralph Shillington


2 Answers

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.

like image 96
Pavlo Glazkov Avatar answered Oct 19 '22 16:10

Pavlo Glazkov


There are several solutions to your problem, but in my opinion, the best solutions are the ones which uses only styles with the standard WPF DataGrid control without inventing a new inherited DataGird type or depending on another third-party control. The followings are the best solutions I found:

  • Option 1: which I personally use: Automatic WPF Toolkit DataGrid Filtering
  • Option 2: Auto-filter for Microsoft WPF DataGrid
like image 21
Mohammed A. Fadil Avatar answered Oct 19 '22 14:10

Mohammed A. Fadil