tldr:CollectionViewSource.Filter被另一个控件覆盖。如何进行两层过滤,以便控件只能看到预过滤的集合?
我有一个第三方gridcontrol,我通过ICollectionView绑定到我的viewmodel中的一个集合。
private CollectionViewSource _filteredCollection;
public ItemListViewModel (List<ItemViewModel> items)
{
_items = items;
_filteredCollection = new CollectionViewSource {Source = _items};
}
public ICollectionView AllInstructions
{
get { return _filteredCollection.View; }
}
这很好用,允许gridcontrol自己进行过滤,分组和排序。 现在我想在网格之前应用我自己的过滤器(即只显示今天项目的按钮)
public ItemListViewModel (List<ItemViewModel> items)
{
...
_filteredCollection.Filter += new FilterEventHandler(FilterByDate);
}
private void FilterByDate(object sender, FilterEventArgs e)
{
var item = e.Item as ItemViewModel;
if (item == null)
{
e.Accepted = false;
}
else
{
e.Accepted = item.CreatedDate >= _selectedDate;
}
}
我的新过滤器按预期工作。 问题是,gridcontrol不能很好地使用它,只是覆盖任何过滤器。
我的想法是在_filteredCollection CVS上执行我的过滤,然后在它周围创建另一个我传递给gridcontrol的CollectionViewSource或CollectionView。
如果我在ICollectionView中包装_filteredCollection,则两层过滤工作完美但我无法排序或分组,因为ICollectionView的默认构造函数将CanSort和CanGroup设置为false。
我无法弄清楚如何将_filteredCollection提供给第二个CollectionViewSource的构造函数。是否有可能或者我是从错误的角度处理这个问题?
答案 0 :(得分:2)
如果我理解正确,您想在列表中应用多个过滤器,不是吗?
如何将Filter过滤到管理多个谓词的主FilterHandler。为了使其更灵活,您可以将这些谓词添加到主FilterHandler将取消堆栈的列表或堆栈中。由于CollectionViewSources的刷新过程,我相信在下一个Refresh()时会考虑任何新的过滤器。
答案 1 :(得分:2)
您可以通过从ListCollectionView派生来创建自己的预定义过滤器集合视图,如下面的代码所示:
class FilteredListCollectionView : ListCollectionView
{
// internal filter
private Predicate<object> preFilter;
// public filter
private Predicate<object> filter;
public FilteredListCollectionView(IList list)
: base(list)
{
}
private Predicate<object> GetCombinedFilter()
{
if (this.preFilter != null)
return this.filter != null ? x => this.preFilter(x) && this.filter(x) : this.preFilter;
else
return this.filter;
}
public Predicate<object> PreFilter
{
get { return this.preFilter; }
set
{
this.preFilter = value;
base.Filter = this.GetCombinedFilter();
}
}
public override Predicate<object> Filter
{
get { return base.Filter; }
set
{
this.filter = value;
base.Filter = this.GetCombinedFilter();
}
}
}
现在您可以像这样使用它:
private FilteredListCollectionView _filteredCollection;
public ItemListViewModel(List<ItemViewModel> items)
{
_items = items;
_filteredCollection = new FilteredListCollectionView(_items);
_filteredCollection.PreFilter = FilterByDate;
}
public ICollectionView AllInstructions
{
get { return _filteredCollection; }
}
private bool FilterByDate(object obj)
{
var item = obj as ItemViewModel;
if (item == null)
{
return false;
}
else
{
return item.CreatedDate >= _selectedDate;
}
}
我没有用任何控件对此进行测试,但我认为它应该可行。