3

在WinRT中似乎无法过滤ObservableCollectionwith :CollectionViewSource

看这里!

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

4

2 回答 2

4

我最终编写了自己的课程以达到预期的效果:

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

还不完美。所以欢迎改进/建议。

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

于 2013-04-27T11:28:04.483 回答
0

您需要确保过滤更改是可观察的,因此您可以将源设置CollectionViewSource为 anObservableCollection并对该集合进行更改,或者将新Source的 CVS 分配给新的过滤集合。

于 2013-04-26T22:11:43.853 回答