编辑解决F Ruffell的答案
我有以下xaml
<StackPanel>
<ListBox x:Name="_list1"/>
<ListBox x:Name="_list2"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
这个代码隐藏:
var ints = new[] { 1, 2, 3 };
_list1.ItemsSource = ints;
_list2.ItemsSource = ints;
_list1.Items.Filter = i => ((int)i) < 2;
Run Code Online (Sandbox Code Playgroud)
出于某种原因,在设置过滤器后,仅对第一个ListBox 列表进行过滤.我希望列表完全不同CollectionViews,确实如此_list1.Items != _list2.Items.同时设置过滤器到其中一个也以某种方式设置非常过滤到另一个.
现在的问题是,为什么和如何被CollectionViews同步?
当你设置ItemsSourceWPF实际上是CollectionView从指定创建一个IEnumerable.它这样做是为了有一个选定项目的概念,过滤,分组等(IEnumerable分配给它们都不支持ItemsSource).当多次使用相同的底层集合时,WPF将同步两个CollectionView.如果你不希望这种行为,简单地设置IsSynchronizedWithCurrentItem到False每个ListBox.
有关更多信息,请参阅
编辑
经过进一步调查,似乎设置IsSynchronizedWithCurrentItem实际上只适用于所选项目,并且两者之间的所有其他属性ICollectionViews仍然是同步的(即使每个属性ListBox都有自己的ICollectionView- 更改Filter或添加SortDescription到一个,将其添加到另一个,您每天学些新东西 :) ).
要更改此行为,您需要自己创建ICollectionViewfor ListBox,然后直接修改Filter属性,例如:
var ints = new[] { 1, 2, 3 };
var viewOne = new ListCollectionView(ints);
var viewTwo = new ListCollectionView(ints);
_list1.ItemsSource = viewOne;
_list2.ItemsSource = viewTwo;
viewOne.Filter = i => ((int)i) < 2;
Run Code Online (Sandbox Code Playgroud)
干杯!
问题是 CollectionViews 为什么以及如何同步?
它们是同步的,因为即使两者ListBoxes具有不同的Items,但它们共享相同的CollectionView,这是源集合的默认视图。
的Items属性ItemsControl是类型ItemCollection,CollectionView属性ItemCollection是内部的,所以我们不能直接访问它来验证这是真的。但是,我们可以在调试器中输入这三个值来验证这一点,它们都为真
_list1.Items.CollectionView == _list2.Items.CollectionView // true
_list1.Items.CollectionView == CollectionViewSource.GetDefaultView(ints) // true
_list2.Items.CollectionView == CollectionViewSource.GetDefaultView(ints) // true
Run Code Online (Sandbox Code Playgroud)
或者,我们可以使用反射在代码中进行比较
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);
Run Code Online (Sandbox Code Playgroud)
F Ruffell已经发布了解决此问题的方法,为每个创建一个新的ListCollectionViewas 。ItemsSourceListBox
_list1.ItemsSource = new ListCollectionView(ints);
_list2.ItemsSource = new ListCollectionView(ints);
Run Code Online (Sandbox Code Playgroud)
另请注意,在此之后,上面的 3 个比较结果为 false
| 归档时间: |
|
| 查看次数: |
917 次 |
| 最近记录: |