问题描述
我正在使用 MVVM 设计模式,将 ListView 绑定到 ViewModel 上的 ListCollectionView.我还有几个用于过滤 ListView 的组合框.当用户从组合框中选择一个项目时,ListView 将针对所选项目进行过滤.每当我想在已经过滤的内容之上进行过滤时,它就会像从未发生过一样撤消我之前的过滤器.移除过滤器也是如此.删除一个组合框的过滤器会删除所有过滤器并显示原始列表.是否可以在同一个 ListCollectionView 上有多个单独的过滤器?
I'm using the MVVM design pattern, with a ListView bound to a ListCollectionView on the ViewModel. I also have several comboboxes that are used to filter the ListView. When the user selects an item from the combobox, the ListView is filtered for the selected item. Whenever I want to filter on top of what is already filtered, it undoes my previous filter like it never happened. The same is also true for removing a filter. Removing a filter for one combobox removes all filters and displays the original list. Is it possible to have multiple, separate filters on the same ListCollectionView?
我做错了什么,还是根本不支持?您可以找到我的应用程序的屏幕截图 amBsX1YHFezrV">ImBsX1YHFazrV">ImBsX1YHFezrV"试图完成.这是我的过滤代码...
Am I doing something wrong, or is this simply not supported? You can find a screen capture of my application here to see what I am trying to accomplish. Here's my code for filtering...
/// <summary>
/// Filter the list
/// </summary>
/// <param name="filter">Criteria and Item to filter the list</param>
[MediatorMessageSink("FilterList", ParameterType = typeof(FilterItem))]
public void FilterList(FilterItem filter)
{
// Make sure the list can be filtered...
if (Products.CanFilter)
{
// Now filter the list
Products.Filter = delegate(object obj)
{
Product product = obj as Product;
// Make sure there is an object
if (product != null)
{
bool isFiltered = false;
switch (filter.FilterItemName)
{
case "Category":
isFiltered = (product.Category.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false;
break;
case "ClothingType":
isFiltered = (product.ClothingType.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false;
break;
case "ProductName":
isFiltered = (product.ProductName.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false;
break;
default:
break;
}
return isFiltered;
}
else
return false;
};
}
}
推荐答案
每次设置过滤器属性时,都会重置上一个过滤器.这是事实.现在你怎么能有多个过滤器?
Every time you set Filter property you reset previous filter. This is a fact. Now how can you have multiple filters?
如您所知,有两种方法可以进行过滤:CollectionView
和 CollectionViewSource
.在 CollectionView
的第一种情况下,我们使用委托进行过滤,并且要执行多个过滤器,我将创建一个类来聚合自定义过滤器,然后为每个过滤器项一个一个地调用它们.就像下面的代码:
As you know, there are two ways to do filtering: CollectionView
and CollectionViewSource
. In the first case with CollectionView
we filter with delegate, and to do multiple filters I'd create a class to aggregate custom filters and then call them one by one for each filter item. Like in the following code:
public class GroupFilter
{
private List<Predicate<object>> _filters;
public Predicate<object> Filter {get; private set;}
public GroupFilter()
{
_filters = new List<Predicate<object>>();
Filter = InternalFilter;
}
private bool InternalFilter(object o)
{
foreach(var filter in _filters)
{
if (!filter(o))
{
return false;
}
}
return true;
}
public void AddFilter(Predicate<object> filter)
{
_filters.Add(filter);
}
public void RemoveFilter(Predicate<object> filter)
{
if (_filters.Contains(filter))
{
_filters.Remove(filter);
}
}
}
// Somewhere later:
GroupFilter gf = new GroupFilter();
gf.AddFilter(filter1);
listCollectionView.Filter = gf.Filter;
要刷新过滤视图,您可以调用 ListCollectionView.Refresh()
方法.
To refresh filtered view you can make a call to ListCollectionView.Refresh()
method.
在第二种情况下,CollectionViewSource
使用 Filter
事件来过滤集合.您可以创建多个事件处理程序以按不同条件进行过滤.要阅读有关此方法的更多信息,请查看 Bea Stollnitz 撰写的这篇精彩文章:如何应用多个过滤器?(存档)
And in the second case with CollectionViewSource
you use Filter
event to filter collection. You can create multiple event handlers to filter by different criteria. To read more about this approach check this wonderful article by Bea Stollnitz: How do I apply more than one filter? (archive)
希望这会有所帮助.
干杯,安瓦卡.
这篇关于WPF 在同一个 ListCollectionView 上使用多个过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!