看来,过滤与CollectionViewSource
的ObservableCollection
的WinRT不可能在:metro应用CollectionViewSource的ObservableCollection过滤
我可以用LINQ过滤器,但我怎么得到UI是否更新影响过滤数据的更改?
看来,过滤与CollectionViewSource
的ObservableCollection
的WinRT不可能在:metro应用CollectionViewSource的ObservableCollection过滤
我可以用LINQ过滤器,但我怎么得到UI是否更新影响过滤数据的更改?
我结束了写我自己的类来达到预期的效果:
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属性的控件。
你需要确保过滤变化是可观的,所以你可以CollectionViewSource
源设置为ObservableCollection
,并在该集合的变化,或者给CVS的新Source
到一个新的,过滤收集。
我有一个源ObservableCollection,我筛选并返回IEnumerable。然后,我将它传递给ObservableCollection的构造函数并分配给CollectionViewSource。对源ObservableCollection进行更新。现在,它们是源代码和已过滤集合之间的断开连接,因此对源代码的更改不会被过滤器拾取。我如何克服这一点? – c0D3l0g1c 2013-04-27 05:25:01
您需要过滤并重新分配。或者,在更新原始更新集时更新已过滤的集合。 – 2013-04-27 19:38:02
我有......见下面的答案。 – c0D3l0g1c 2013-04-27 19:54:56
不完美......是!你能展示一个简单的使用示例吗?理解这个课堂的目的/优点会更好。 – letiagoalves 2013-04-30 16:50:20
用途:可分类和过滤的ObservableCollection。创建此对象的实例,像通常使用ObservableCollection一样使用。具有谓词形式的过滤器属性,因此您可以过滤数据。然后绑定到控件时,绑定到View属性。而已! – c0D3l0g1c 2013-04-30 17:24:31
不错的解决方案。我将暂时在我的项目中使用它! – 2015-01-27 17:27:20