我的代码隐藏构建了一个
CollectionViewSource
来对表示磁盘文件夹的对象集合进行排序和过滤。它将其视图公开给我的 XAML。我最初编写了这样的代码来构建对象
var cvsFolder = new CollectionViewSource()
{
Source = _scansSource.Items,
View = { Filter = IsScan } // Only show folders that are "scans"
};
// Sort by desired property -- this clears out the filter
cvsFolder.SortDescriptions.Add(new SortDescription(propertyName, dir));
但是我的过滤器不起作用。在我的用户界面中,我看到了所有文件夹。
一些调试表明问题是我在最后一行对
SortDescriptions.Add
的调用立即清除了我刚刚在其上方添加了几行的过滤器。 (要么它要么完全取代了视图。我不确定是哪一个)
所以我改变了顺序。像这样
var cvsFolder = new CollectionViewSource() { Source = _scansSource.Items, };
cvsFolder.SortDescriptions.Add(new SortDescription(propertyName, dir));
cvsFolder.View.Filter = IsScan; // Set the filter after adding sort descriptions
这有效;我的数据现已排序和过滤。但这种行为是出乎意料的,并且有点令人担忧。
这是否意味着,如果想动态更改排序(添加或删除描述或更改方向),随着时间的推移,我每次都必须重置过滤器?
CollectionViewSource
中是否还有其他属性可能具有类似的影响或受到类似的影响?
或者我只是以错误的方式这样做?
通常,您不会在 C# 代码中使用
CollectionViewSource
。相反,您可以直接访问 ICollectionView
。 CollectionViewSource
是 IcollectionView
的简单包装。它将所有属性值转发给底层 ICollectionView
。显然,它还会重置 ICollectionView.Filter
属性。CollectionViewSource
的目的是为XAML代码提供API来管理ICollectionView
。由于您可以使用 C# 直接访问它,因此不需要它。
在 WPF 中,当绑定到集合时,绑定引擎会为源集合创建一个
CollectionView
并跟踪它的更改以更新绑定目标。 ItemsControl
控件本质上是绑定到集合的 ICollectionView
,而不是集合本身。
因此,您可以修改默认值
ICollectionView
,例如通过添加过滤和排序,ItemsControl
将相应更新(尽管绑定使用集合作为源)。排序、过滤和分组仅适用于 ICollectionView
,而不适用于底层集合。
// Let's assume a e.g. ListBox binds to the _scansSource.Items property.
// Then modifications of the default ICollectionView of _scansSource.Items will be reflected in the ListBox:
var items = _scansSource.Items;
ICollectionView itemsView = CollectionViewSource.GetDefaultView(items);
itemsView.Filter = IsScan;
itemsView.SortDescriptions.Add(new SortDescription(propertyName, dir));
如果
_scansSource
是ItemsControl
,也可以直接过滤排序:
itemsControl.Items.Filter = IsScan;
itemsControl.Items.SortDescriptions.Add(new SortDescription(propertyName, dir));