2017-02-14 10 views
0

В моем WPF Window у меня есть DataGrid контроль с его ItemsSource, связанным с ObservableCollection элементов (скажем, простой объект с парой свойств):WPF: Фильтрация DataGrid на лету

XAML:(Удалены некоторые Xmlns вещи для краткости)

<Window> 
    <Window.Resources> 
     <CollectionViewSource x:Key="MyViewSource" 
           Source="{Binding MyItemList}" 
           Filter="MyItemList_Filter"/> 
    </Window.Resources> 

    <Window.DataContext> 
     <!-- Some Ioc stuff --> 
    </Window.DataContext> 

    <StackPanel> 
     <TextBox Text="{Binding TextFilter}" /> 
     <DataGrid Grid.Row="1" x:Name="dataGrid" 
      ItemsSource="{Binding Source={StaticResource MyViewSource}}" 
      SelectionUnit="FullRow" 
      SelectionMode="Extended" 
      CanUserAddRows="False" 
      CanUserDeleteRows="False" 
      HeadersVisibility="Column" /> 
    </StackPanel> 
</Window> 

ViewModel (CS):

public class ViewModel : ViewModelBase // From Galasoft MVVM Light toolkit 
{ 

    #region TextFilter Property 
    public const string TextFilterPropertyName = "TextFilter"; 

    private string _TextFilter; 

    public string TextFilter 
    { 
     get 
     { 
      return _TextFilter; 
     } 

     set 
     { 
      if (_TextFilter == value) 
      { 
       return; 
      } 

      _TextFilter = value; 

      RaisePropertyChanged(TextFilterPropertyName); 
     } 
    } 
    #endregion // TextFilter Property 

    #region MyItemList Property 
    public const string MyItemListPropertyName = "MyItemList"; 

    private ObservableCollection<Item> _MyItemList; 

    public ObservableCollection<Item> MyItemList 
    { 
     get 
     { 
      return _MyItemList; 
     } 

     set 
     { 
      if (_MyItemList == value) 
      { 
       return; 
      } 

      _MyItemList = value; 

      RaisePropertyChanged(MyItemListPropertyName); 
     } 
    } 
    #endregion // MyItemList Property 


} 

метод фильтрации, из кода окна позади:

private void MyItemList_Filter(object sender, FilterEventArgs e) 
{ 
    var vm = (ViewModel)this.DataContext; 
    var item = (Item)e.Item; 
    // ...Simplified... 
    e.Accepted = item.PropertyToCheck.Contains(vm.TextFilter); 
} 

Фильтрация применяется только при заполнении MyItemList: как я могу сделать MyItemList_Filter назвать (и DataGrid элементы будут показаны/скрытые соответственно) на " live "TextFilter изменить?

Любая помощь будет оценена

ответ

2

Вы можете (должны) переместить логику фильтрации в модели представления, например .:

public class ViewModel : ViewModelBase 
{ 
    public const string TextFilterPropertyName = "TextFilter"; 

    private string _TextFilter; 
    public string TextFilter 
    { 
     get 
     { 
      return _TextFilter; 
     } 
     set 
     { 
      if (_TextFilter == value) 
       return; 
      _TextFilter = value; 
      RaisePropertyChanged(TextFilterPropertyName); 
      Filter(); 
     } 
    } 

    public const string MyItemListPropertyName = "MyItemList"; 

    private ObservableCollection<Item> _MyItemList; 
    public ObservableCollection<Item> MyItemList 
    { 
     get 
     { 
      return _MyItemList; 
     } 
     set 
     { 
      if (_MyItemList == value) 
       return; 

      _MyItemList = value; 
      RaisePropertyChanged(MyItemListPropertyName); 
     } 
    } 

    private ObservableCollection<Item> _filtered; 
    public ObservableCollection<Item> FilteredList 
    { 
     get 
     { 
      return _filtered; 
     } 
     set 
     { 
      if (_filtered == value) 
       return; 

      _filtered = value; 
      RaisePropertyChanged("FilteredList"); 
     } 
    } 

    private void Filter() 
    { 
     _filtered.Clear(); 
     foreach(var item in _MyItemList) 
     { 
      if (item.PropertyToCheck.Contains(TextFilter)) 
       _filtered.Add(item); 
     } 
    } 
} 

Вот где она принадлежит. Тогда вам не нужно использовать CollectionViewSource:

<DataGrid Grid.Row="1" x:Name="dataGrid" ItemsSource="{Binding FilteredList}" ... /> 
+0

Это работает, спасибо. Вы сказали, что фильтрация - это материал, связанный с ViewModel, но я почти не согласен ... –

+2

Если у вас есть пользовательская логика фильтрации, это, безусловно, относится к модели представления, если вы намерены соблюдать шаблон MVVM. Исключением может быть это, если вы реализуете некоторые очень общие функции фильтра, которые являются, например, частью функциональности элемента управления. Но если вы фильтруете на основе значения свойства в вашей модели представления, логика фильтрации должна быть реализована в модели представления. – mm8