WPF ListBoxes的ItemsSource奇怪的行为 [英] Wpf ListBoxes' ItemsSource strange behaviour
问题描述
编辑以解决 F Ruffell的答案
我有以下xaml
<StackPanel>
<ListBox x:Name="_list1"/>
<ListBox x:Name="_list2"/>
</StackPanel>
以及以下代码:
var ints = new[] { 1, 2, 3 };
_list1.ItemsSource = ints;
_list2.ItemsSource = ints;
_list1.Items.Filter = i => ((int)i) < 2;
由于某些原因,仅对第一个 ListBox
设置过滤器后,两个列表都被过滤.我希望列表具有完全不同的 CollectionViews
和确实是 _list1.Items!= _list2.Items
.同时将filter设置为其中一个还可以以某种方式将该filter设置为另一个.
问题是为什么和如何同步 CollectionViews
?
For some reason after setting filter only for the first ListBox
both lists are filtered. I expect the lists to have completely different CollectionViews
and indeed _list1.Items != _list2.Items
. Meanwhile setting filter to one of them also somehow sets that very filter to the other.
The question is why and how are CollectionViews
synchronized?
推荐答案
问题是,为什么以及如何同步CollectionViews?
The question is why and how are CollectionViews synchronized?
它们是同步的,因为即使两个 ListBoxes
具有不同的 Items
,它们也共享相同的 CollectionView
,这是源的默认视图集合.
They are synchronized because even though both ListBoxes
have different Items
, they share the same CollectionView
, which is the default view for the source collection.
ItemsControl 的 Items
属性的类型为 ItemCollection
和 ItemCollection
是内部,因此我们无法直接访问它以验证这是正确的.但是,我们只需要在调试器中输入这三个值即可进行验证,它们全部显示为真
The Items
property of ItemsControl
is of type ItemCollection
and the CollectionView
property of ItemCollection
is internal so we can't access it directly to verify that this is true. However, we can just enter these three values in the debugger to verify this, they all come out as true
_list1.Items.CollectionView == _list2.Items.CollectionView // true
_list1.Items.CollectionView == CollectionViewSource.GetDefaultView(ints) // true
_list2.Items.CollectionView == CollectionViewSource.GetDefaultView(ints) // true
或者,我们可以使用反射在代码中进行比较
Alternatively, we can use reflection to do the comparison in code
PropertyInfo collectionViewProperty =
typeof(ItemCollection).GetProperty("CollectionView", BindingFlags.NonPublic | BindingFlags.Instance);
ListCollectionView list1CollectionView = collectionViewProperty.GetValue(_list1.Items, null) as ListCollectionView;
ListCollectionView list2CollectionView = collectionViewProperty.GetValue(_list2.Items, null) as ListCollectionView;
ListCollectionView defaultCollectionView = CollectionViewSource.GetDefaultView(ints) as ListCollectionView;
Debug.WriteLine(list1CollectionView == list2CollectionView);
Debug.WriteLine(list1CollectionView == defaultCollectionView);
Debug.WriteLine(list2CollectionView == defaultCollectionView);
解决此问题的方法已经由 F Ruffell 发布,为每个 ListBox创建一个新的
ListCollectionView
作为 ItemsSource
.
The way to work around this has already been posted by F Ruffell, create a new ListCollectionView
as ItemsSource
for each ListBox
.
_list1.ItemsSource = new ListCollectionView(ints);
_list2.ItemsSource = new ListCollectionView(ints);
还请注意,此后,上面的3个比较为假
这篇关于WPF ListBoxes的ItemsSource奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!