回答

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属性的控件。

+0

不完美......是!你能展示一个简单的使用示例吗?理解这个课堂的目的/优点会更好。 – letiagoalves 2013-04-30 16:50:20

+1

用途:可分类和过滤的ObservableCollection。创建此对象的实例,像通常使用ObservableCollection一样使用。具有谓词形式的过滤器属性,因此您可以过滤数据。然后绑定到控件时,绑定到View属性。而已! – c0D3l0g1c 2013-04-30 17:24:31

+0

不错的解决方案。我将暂时在我的项目中使用它! – 2015-01-27 17:27:20

0

你需要确保过滤变化是可观的,所以你可以CollectionViewSource源设置为ObservableCollection,并在该集合的变化,或者给CVS的新Source到一个新的,过滤收集。

+0

我有一个源ObservableCollection,我筛选并返回IEnumerable。然后,我将它传递给ObservableCollection的构造函数并分配给CollectionViewSource。对源ObservableCollection进行更新。现在,它们是源代码和已过滤集合之间的断开连接,因此对源代码的更改不会被过滤器拾取。我如何克服这一点? – c0D3l0g1c 2013-04-27 05:25:01

+0

您需要过滤并重新分配。或者,在更新原始更新集时更新已过滤的集合。 – 2013-04-27 19:38:02

+0

我有......见下面的答案。 – c0D3l0g1c 2013-04-27 19:54:56

相关问题