Metro App CollectionViewSource ObservableCollection Filter

时间:2013-04-26 20:20:25

标签: windows-runtime microsoft-metro winrt-xaml observablecollection collectionviewsource

WinRT 中,无法使用ObservableCollection过滤CollectionViewSource

See here!

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

2 个答案:

答案 0 :(得分: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属性将此对象直接绑定到控件。

答案 1 :(得分:0)

您需要确保过滤更改是可观察的,因此您可以将CollectionViewSource的来源设置为ObservableCollection并对该集合进行更改或指定新的Source将CVS添加到新的过滤集合中。