Итак, я нашел решение, которое также учитывает MVVM. Это может быть не самым элегантным, но, возможно, это можно рассматривать как кикстарт, который можно реорганизовать и улучшить. Прежде всего: вам нужно создать экземпляр CollectionViewSource, а не устанавливать ICollectionView. Итак, в вашей viewModel:
public CollectionViewSource _primaryView;
public CollectionViewSource PrimaryView
{
get {return _primaryView; }
set
{
_primaryView = value;
PropertyChange(nameof(_primaryView);
}
}
Также создайте экземпляр вашей коллекции элементов, которые вы хотите отфильтровать. В моем случае:
//This is the collection you want to filter. In my case it holds fields for
//objects of type item, element and value.
public ObservableCollection<FilterObjects> DefaultFilter {get; set;} = new
ObservableCollection<FilterObject>();
Затем вам нужно будет установить источник PrimaryView для вашей коллекции (ту, которую вы хотите отфильтровать). Мы устанавливаем это в конструкторе viewModel. Итак, в моем случае:
public MainViewModel()
{
//Here I fill my dummy data to my collection I want to filter
// -- load dummy data --
//Then set PrimaryView.Source to the collection you want to filter
PrimaryView.Source = DefaultFilter;
}
Далее настройте фильтры. Поэтому вам нужно два ComboBox в вашем представлении. Вот так:
<ComboBox x:Name="cmbItemFilter" Margin="10" ItemsSource="{Binding ItemsList}"
SelectedIndex="0" SelectedItem="{Binding CurrentItem}">
</ComboBox>
ItemsList - это просто еще одно свойство в моей viewModel, и в основном это список объектов элементов. CurrentItem - это свойство типа string, которое содержит выбранный в данный момент элемент comboBox. Не забудьте поднять здесь PropertyChange:
private string _currentItem;
public string CurrentItem
{
get { return _currentItem; }
set
{
_currentItem = value;
PropertyChange(nameof(_currentItem));
}
}
Выполните соответствующие действия для любого другого комбинированного списка, который вы можете использовать в качестве фильтра. Итак, в моем случае, у меня есть еще два comboBox, связанные со списком типа элемента и списком типа значения. Аналогично, каждый выбранный элемент comboBox привязан к свойству в моей viewModel (CurrentElement, CurrentValue). Убедитесь, что ваш dataContext для вашего представления установлен на viewModel. Мне нравится делать это в XAML, поэтому вот оно:
<Window.DataContext>
<viewModels:MainViewModel/>
</Window.DataContext>
ViewModels - это пространство имен, которое необходимо импортировать в операторы моего представления. Это довольно просто, но если вы не знакомы с этим: поместите все ваши viewModels в папку вашего решения под названием «ViewModels». Теперь вам нужно сослаться на эту папку в вашем XAML, например, так:
<Window x:Class="DataGrid_Templating.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
…
xmlns:viewModels ="clr-namespace:[nameOfYourProjectWithoutRectangularBrackets].
[FoldernameWhereYourViewModels resideWithoutRectangularBrackets]"
Последнее, что вам нужно сделать здесь, это показать вашу сетку данных, откуда она получает данные. Поэтому вам нужно настроить itemsSource следующим образом:
<DataGrid x:Name="dtgMainGrid" ItemsSource="{Binding PrimaryView.View}"
HorizontalContentAlignment="Center"> </DataGrid>
Убедитесь, что это свойство представления CollectionViewSource, к которому вы привязываете, иначе оно просто не будет работать!
From с этого момента все, что вам нужно сделать, это настроить фильтр logi c. Мальчик, это дало мне кошмары, но это работает! Итак, еще раз, go для вашего viewModel, и измените его в свойстве CurrentItem (CurrentElement / CurrentValue):
private string _currentItem;
public string CurrentItem
{
get { return _currentItem; }
set
{
_currentItem = value;
if (CurrentValue == „Show all Items“)
{
ApplyElementFilter();
ApplyValueFilter();
}
else
{
ApplyItemFilter();
}
PropertyChange(nameof(_currentItem));
}
}
Эта часть очень сложная, и я до сих пор не уверен, что происходит здесь - я получил желаемый результат более или менее благодаря счастливой случайности ... Просто убедитесь, что если у вас есть критерии фильтра, такие как «Выбрать всех людей» или «Показать все категории» (вроде настройки по умолчанию), он запустит все другие фильтры, которые у вас есть at посмотрите в следующем параграфе, я уверен, что код является тихим пояснением об этом. ApplyElementFilter () и ApplyValueFilter (или любой другой фильтр, который вам нравится) должны быть реализованы в вашей viewModel:
private void ApplyItemFilter()
{
PrimaryView.Filter -= new FilterEventHandler(FilterByItems);
PrimaryView.Filter += new FilterEventHandler(FilterByItems);
}
private void ApplyElementFilter()
{
PrimaryView.Filter -= new FilterEventHandler(FilterByElement);
PrimaryView.Filter += new FilterEventHandler(FilterByElement);
}
private void ApplyValueFilter()
{
PrimaryView.Filter -= new FilterEventHandler(FilterByValue);
PrimaryView.Filter += new FilterEventHandler(FilterByValue);
}
Вы близки к этому, так что терпите меня. Последнее, что вам нужно сделать, это назначить методы, на которые вы ссылаетесь в FilterEventHandler. Они все одинаковы, поэтому для простоты я обращаюсь только к одному:
public void FilterByItems(object sender, FilterEventArgs e)
{var sr c = e.Item as Item;
if (src == null)
{
e.Accepted = false;
else if (CurrentItem== "Show all Items")
e.Accepted = true;
}
else if (string.Compare(CurrentItem, src.CurrentItem) != 0)
{
e.Accepted = false;
}
Это поначалу многое нужно проглотить, но, как я уже говорил, я уверен, что есть способы получить эту функциональность и сделать ее более элегантной. Надеюсь, кто-то там может использовать это. Приветствия