Windows runtime Metro App CollectionViewSource ObservableCollection筛选器

Windows runtime Metro App CollectionViewSource ObservableCollection筛选器,windows-runtime,microsoft-metro,winrt-xaml,observablecollection,collectionviewsource,Windows Runtime,Microsoft Metro,Winrt Xaml,Observablecollection,Collectionviewsource,在WinRT中,似乎无法使用CollectionViewSource过滤ObservableCollection: 我可以使用LINQ进行过滤,但是如果进行了影响过滤数据的更改,我如何让UI进行更新?您需要确保过滤更改是可见的,因此,您可以将CollectionViewSource的源设置为observateCollection,并对该集合进行更改,或者将CV的新源指定给新的过滤集合。我最终编写了自己的类以实现所需的效果: public class ObservableCollectionVi

WinRT中,似乎无法使用
CollectionViewSource
过滤
ObservableCollection


我可以使用LINQ进行过滤,但是如果进行了影响过滤数据的更改,我如何让UI进行更新?

您需要确保过滤更改是可见的,因此,您可以将
CollectionViewSource
的源设置为
observateCollection
,并对该集合进行更改,或者将CV的新
源指定给新的过滤集合。

我最终编写了自己的类以实现所需的效果:

public class ObservableCollectionView<T> : ObservableCollection<T>
{
    private ObservableCollection<T> _view;
    private Predicate<T> _filter;

    public ObservableCollectionView(IComparer<T> comparer)
        : base(comparer)
    {

    }

    public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection)
        : base(comparer, collection)
    {

    }

    public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection, Predicate<T> filter)
        : base(comparer, collection == null ? new T[] { } : collection)
    {
        if (filter != null)
        {
            _filter = filter;

            if (collection == null)
                _view = new ObservableCollection<T>(comparer);
            else
                _view = new ObservableCollection<T>(comparer, collection);
        }
    }

    public ObservableCollection<T> View
    {
        get
        { 
            return (_filter == null ? this : _view);
        }
    }

    public Predicate<T> Filter
    {
        get
        {
            return _filter;
        }
        set
        {
            if (value == null)
            {
                _filter = null;
                _view = new ObservableCollection<T>(Comparer);
            }
            else
            {
                _filter = value;
                Fill();
            }
        }
    }

    private void Fill()
    {
        _view = new ObservableCollection<T>(Comparer);
        foreach (T item in this)
        {
            if (Filter(item))
                View.Add(item);
        }
    }

    private int this[T item]
    {
        get
        {
            int foundIndex = -1;
            for (int index = 0; index < View.Count; index++)
            {
                if (View[index].Equals(item))
                {
                    foundIndex = index;
                    break;
                }
            }
            return foundIndex;
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnCollectionChanged(e);

        if (_filter != null)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (T item in e.NewItems)
                        if (Filter(item))
                            View.Add(item);
                    break;

                case NotifyCollectionChangedAction.Move:

                    break;

                case NotifyCollectionChangedAction.Remove:
                    foreach (T item in e.OldItems)
                        if (Filter(item))
                            View.Remove(item);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    for (int index = 0; index < e.OldItems.Count; index++)
                    {
                        T item = (T)e.OldItems[index];
                        if (Filter(item))
                        {
                            int foundIndex = this[item];
                            if (foundIndex != -1)
                                View[foundIndex] = (T)e.NewItems[index];
                        }
                    }
                    break;

                case NotifyCollectionChangedAction.Reset:
                    Fill();
                    break;
            }
        }
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);

        if (_filter != null)
        {
    // TODO: Implement code for property changes
        }
    }
}
公共类ObservableCollection视图:ObservableCollection
{
私有可观察收集视图;
私有谓词过滤器;
公共可见集合视图(IComparer比较器)
:基准(比较器)
{
}
公共ObservableCollectionView(IComparer比较器、IEnumerable集合)
:base(比较器、集合)
{
}
公共ObservableCollectionView(IComparer比较器、IEnumerable集合、谓词筛选器)
:base(比较器,集合==null?新的T[]{}:collection)
{
if(过滤器!=null)
{
_过滤器=过滤器;
if(集合==null)
_视图=新的可观察集合(比较器);
其他的
_视图=新的可观察集合(比较器、集合);
}
}
公共可观测集合视图
{
得到
{ 
返回(_filter==null?此:_视图);
}
}
公共谓词过滤器
{
得到
{
返回过滤器;
}
设置
{
如果(值==null)
{
_filter=null;
_视图=新的可观察集合(比较器);
}
其他的
{
_过滤器=值;
填充();
}
}
}
私人空间填充()
{
_视图=新的可观察集合(比较器);
foreach(本文件中的T项)
{
if(过滤器(项目))
查看。添加(项目);
}
}
私人int本[T项]
{
得到
{
int foundIndex=-1;
for(int index=0;index
还不完美。因此,欢迎改进/建议


现在可以使用View属性将此对象直接绑定到控件。

我有一个源ObservableCollection,我过滤它并返回IEnumerable。然后我将其传递给ObservableCollection的构造函数并分配给CollectionViewSource。对源ObservableCollection进行更新。现在,源集合和已筛选集合之间的连接断开,因此对源集合所做的更改不会被筛选器拾取。如何克服此问题?您需要再次筛选并分配它。或者在更新原始集合时更新筛选的集合。我有。。。见下面我的答案。不完美。。。然而你能举一个简单的用法例子吗?最好理解这个类的目的/优点。目的:一个可排序和过滤的ObservableCollection。创建此对象的实例,像通常使用ObservableCollection一样使用。具有谓词形式的筛选器属性,因此可以筛选数据。然后在绑定到控件时,绑定到View属性。就这样!很好的解决方案。我将在我的项目中使用这个暂时!我不理解是否存在使用
IComparer
参数的构造函数重载。这些重载不存在于
ObservableCollection
中,因此a)在该视图实现中似乎不需要它们,b)上述内容不会编译,因为
base
调用无效(重载不存在于基类中)。