Metro App CollectionViewSource ObservableCollection Filter

谁说胖子不能爱 提交于 2019-12-03 20:43:39

I ended up writing my own class to achieve the desired effect:

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

Not yet perfect. So improvements/suggestions welcomed.

You can now bind this object, directly to a control using the View property.

You need to make sure the filtering changes are observable, so you can set the source of the CollectionViewSource to an ObservableCollection and make the changes on that collection or assign a new Source of the CVS to a new, filtered collection.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!