CollectionViewSource在属性更改时不会重新排序

14
我正在将ItemsControl绑定到CollectionViewSource。以下是代码:
this.Trucks = new ObservableCollection<Truck>();
            foreach (var truck in DataRepository.Trucks.Where(t => t.ReadyDate.Date.Equals(this.Date)))
            {
                this.Trucks.Add(truck);
            }

            this.TrucksSource = new CollectionViewSource { Source = this.Trucks };
            this.TrucksSource.SortDescriptions.Add(new SortDescription("ReadyAddress.Region.RegionNumber", ListSortDirection.Ascending));
            this.TrucksSource.SortDescriptions.Add(new SortDescription("TruckId", ListSortDirection.Ascending));

当我最初进行绑定时,排序是有效的。当我向ObservableCollection添加项目时,它会被插入到正确的位置,这很好。但是当我更改按其排序的属性时,此项未在列表中“移动”。

ReadyAddress.Region.RegionNumber 正确地引发了 INotifyPropertyChanged,我在绑定字段中看到了它,但顺序没有改变。我是否期望不应该发生的事情,或者有更好的方法来处理这种情况?


1
请查看我的答案,了解SortDescription和自动排序顺序刷新 - LPL
1
WPF 4.5 中有一个名为“实时整形”的新功能,可以解决这个问题。但是,如果您不想调用“刷新”方法,暂时可能需要使用 LPL 提供的链接方法。 - Kris
我通过简单地在公开视图的属性上调用PropertyChanged来修复了这个问题,让视图刷新(并清除排序),然后添加排序描述。 - PatFromCanada
3个回答

13

虽然回答晚了,但是在4.5版本中,ListCollectionView(ListBox和CollectionViewSource.View的默认实现)新增了一些属性来实现这一点。

你可以使用IsListSorting和ListSortingProperties属性来启用自动重新排序功能。同时,它不会重建视图。

list.SortDescriptions.Add(new SortDescription("MyProperty", ListSortDirection.Ascending));
list.IsLiveSorting = true;
list.LiveSortingProperties.Add("MyProperty");

当属性MyProperty发生变化时,应该重新排序。


在XAML中,您可以使用CollectionViewSource的IsLiveSortingRequested="True"属性: <CollectionViewSource x:Key="ListSorted" Source="{Binding ListUnsorted}" IsLiveSortingRequested="True" > <CollectionViewSource.SortDescriptions> <cm:SortDescription PropertyName="Name" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource>其中 xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase" - Ivanhoe
在XAML中,您可以使用CollectionViewSource的IsLiveSortingRequested="True"属性: <CollectionViewSource x:Key="ListSorted" Source="{Binding ListUnsorted}" IsLiveSortingRequested="True" > <CollectionViewSource.SortDescriptions> <cm:SortDescription PropertyName="Name" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource>其中 xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase" - undefined

5
我找到的所有答案都提到了 View.Refresh(),但这对于大型列表来说并不是很好的解决方案。我最终做的是使用Remove()Add()删除和添加该项。然后它会适当地重新定位而不重新加载整个列表。
注意事项!它适用于我的情况,但在您的情况下,移除对象并重新添加可能会导致副作用,具体取决于您的代码编写方式。在我的例子中,这是一个带有UI效果的列表,其中新项目会以过渡效果显示出来,因此刷新将在整个列表上显示过渡效果,而删除/添加则可以很好地展示该项目如何重新定位。

5

你尝试过刷新你的CollectionViewSource吗?

    this.TruckSource.View.Refresh();

4
是的,但我不喜欢它 - 它刷新整个视图。 - katit

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