绑定到集合是如何真正工作的?

10

嗯,我有些困惑。

如果我的控件有一个依赖属性ItemsSource,类型为IEnumerable,用户将集合绑定到它,那么在DependencyPropertyChangedEventArgs.NewValue中有什么对象?

据我所知,WPF会为集合隐式创建CollectionView,并期望args.NewValue的类型是ICollectionView

来自这篇博客

当用户将WPF属性绑定到数据集合时,WPF会自动创建一个视图来包装该集合,并将属性绑定到该视图,而不是原始集合。这种行为始终发生,并且与CollectionViewSource无关。

但是调试器(VS 2012, .net v.4.0)向我显示,我收到了原始的集合,而不是NewValue中的CollectionView。(BindsDirectlyToSource未设置,默认值为false)
这怎么可能?!

我无法理解在这种情况下WPF控件如何支持排序、分组和过滤。
CollectionView是如何注入和使用的?

1个回答

4
也许下面这段摘自CollectionView的“备注”部分的内容可以回答你的问题:
在WPF应用程序中,所有集合都有一个关联的默认集合视图。而不是直接使用集合,绑定引擎总是通过关联的视图访问集合。要获取默认视图,请使用CollectionViewSource.GetDefaultView方法。基于CollectionView的内部类是仅实现IEnumerable接口的集合的默认视图。ListCollectionView是实现IList接口的集合的默认视图。BindingListCollectionView是实现IBindingListView或IBindingList接口的集合的默认视图。
另外,您可以使用CollectionViewSource类以可扩展的应用程序标记语言(XAML)创建集合的视图,然后将控件绑定到该视图。CollectionViewSource类是CollectionView类的XAML表示。有关示例,请参阅如何使用XAML中的视图对数据进行排序和分组。
因此,如果您没有显式地绑定到CollectionViewSource,集合绑定始终会绑定到原始集合(在NewValue中获得),但对集合的访问(例如按索引获取项)始终通过默认视图完成。因此,“将属性绑定到视图而不是原始集合”这一说法并不完全正确。
快速测试显示,GetDefaultView为我绑定的ObservableCollection返回了System.Windows.Data.ListCollectionView。

这意味着我的控件必须请求CollectionView传递的集合,而且没有内置的分组、过滤和排序支持。实现上述功能是控件的责任,不是吗? - Pavel Voronin
1
当您显式地绑定到 CollectionViewSource 时,将为分组、筛选和排序提供开箱即用的支持。请参阅“如何创建视图”中的“绑定到集合”。 - Clemens
仅用于过滤和排序,我相信。您的控件如何知道已创建的组?好的,假设它只获取组,但在这种情况下,源集合中的项目将不可用。 - Pavel Voronin
请参阅分组,其中提到“除了查看IEnumerable集合的内部类之外,所有集合视图都支持分组功能”。 - Clemens
好的,List/BindingListCollectionView 肯定可以。问题是关于我的自定义控件。当它的属性绑定到 CollectionView 时,它仍然必须知道如何处理分组。 - Pavel Voronin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接