tldr:CollectionViewSource.Filter被另一个控件覆盖。我如何有两层过滤,以便控件仅看到预过滤的集合?

我有一个第三方网格控件,该控件通过ICollectionView绑定(bind)到我的 View 模型中的集合。

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上执行过滤,然后围绕它创建另一个CollectionViewSource或CollectionView,并将其传递给gridcontrol。

如果我将_filteredCollection包装在ICollectionView中,则两层过滤可以完美地工作,但是我无法进行排序或分组,因为ICollectionView的默认构造函数的CanSort和CanGroup设置为false。

我不知道如何将_filteredCollection馈入第二个CollectionViewSource的构造函数中。是否有可能或者我从错误的角度来解决这个问题?

最佳答案

您可以通过从ListCollectionView派生预定义的过滤器来创建自己的集合 View ,如以下代码所示:

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;
    }
}

我没有用任何控件测试过,但是我认为它应该可以工作。

关于.net - CollectionViewSources是否可嵌套?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17569832/

10-17 01:22