对 ObservableCollection<object> 进行排序不会更新 UI
Sorting an ObservableCollection<object> doesn't update the UI
我正在开发一个 Windows Phone 8.1 (WinRt) 应用程序。
我有一个ObservableCollection<object>
,我需要添加、修改和排序这个集合的项目。
当我向这个列表添加一个项目时一切正常,如果我在列表中投射这个对象之一并且我编辑对象的 属性 INotifyPropertyChanged
负责更新ui.
但是当我对列表进行排序时,UI 不遵守列表的顺序。
更新 UI 的唯一方法是使用 Move()
,但我发现这种方法非常耗资源。
我已经尝试使用 LINQ,但结果列表是有序的,但 UI 中的元素保持相同的顺序。
有任何其他方法可以对此列表进行排序吗?
这是我的 ViewModel 中的一些代码
ActiveServices = ActiveServices.Where(x => x is ActiveServiceControlData).OrderByDescending(x => (x as ActiveServiceControlData).NotificationNumber).ToObservableCollection();
private static ObservableCollection<object> activeServices;
public ObservableCollection<object> ActiveServices
{
get { return activeServices; }
set
{
activeServices = value;
RaisePropertyChanged(() => ActiveServices);
}
}
编辑
我的大问题是在 ObservableCollection 中有不同类型的对象,我将此集合用作 ListView 的 ItemsSource,并根据 ObservableCollection 中对象的类型使用 ItemTemplateSelector,我只需要排序特定类型的元素。
排序 ObservableCollection
的正确方法是扩展基础 ObservableCollection
并利用内部 CollectionChanged
事件。
您当前的代码重新创建了效率低下的整个集合(并且您的用户界面可能 "blink")。
public class SortableObservableCollection<T, TSortKey> : ObservableCollection<T>
{
private readonly Func<T, TKey> _sortByKey;
public SortableObservableCollection(Func<T, TKey> sortByKey)
{
_sortByKey = sortByKey;
}
public void Sort() {
// slow O(n^2) sort but should be good enough because user interface rarely has milion of items
var sortedList = Items.OrderBy(_sortByKey).ToList();
for (int i = 0; i < sortedList.Count; ++i)
{
var actualItemIndex = Items.IndexOf(sortedList[i]);
if (actualItemIndex != i)
Move(actualItemIndex, i);
}
}
}
.. 然后调用 .Sort();
上述方法比重新创建整个项目源有很大优势 - 您的用户界面可以以漂亮的方式对此做出反应(项目移动的动画而不是重新创建 "blink")
我正在开发一个 Windows Phone 8.1 (WinRt) 应用程序。
我有一个ObservableCollection<object>
,我需要添加、修改和排序这个集合的项目。
当我向这个列表添加一个项目时一切正常,如果我在列表中投射这个对象之一并且我编辑对象的 属性 INotifyPropertyChanged
负责更新ui.
但是当我对列表进行排序时,UI 不遵守列表的顺序。
更新 UI 的唯一方法是使用 Move()
,但我发现这种方法非常耗资源。
我已经尝试使用 LINQ,但结果列表是有序的,但 UI 中的元素保持相同的顺序。
有任何其他方法可以对此列表进行排序吗?
这是我的 ViewModel 中的一些代码
ActiveServices = ActiveServices.Where(x => x is ActiveServiceControlData).OrderByDescending(x => (x as ActiveServiceControlData).NotificationNumber).ToObservableCollection();
private static ObservableCollection<object> activeServices;
public ObservableCollection<object> ActiveServices
{
get { return activeServices; }
set
{
activeServices = value;
RaisePropertyChanged(() => ActiveServices);
}
}
编辑
我的大问题是在 ObservableCollection 中有不同类型的对象,我将此集合用作 ListView 的 ItemsSource,并根据 ObservableCollection 中对象的类型使用 ItemTemplateSelector,我只需要排序特定类型的元素。
排序 ObservableCollection
的正确方法是扩展基础 ObservableCollection
并利用内部 CollectionChanged
事件。
您当前的代码重新创建了效率低下的整个集合(并且您的用户界面可能 "blink")。
public class SortableObservableCollection<T, TSortKey> : ObservableCollection<T>
{
private readonly Func<T, TKey> _sortByKey;
public SortableObservableCollection(Func<T, TKey> sortByKey)
{
_sortByKey = sortByKey;
}
public void Sort() {
// slow O(n^2) sort but should be good enough because user interface rarely has milion of items
var sortedList = Items.OrderBy(_sortByKey).ToList();
for (int i = 0; i < sortedList.Count; ++i)
{
var actualItemIndex = Items.IndexOf(sortedList[i]);
if (actualItemIndex != i)
Move(actualItemIndex, i);
}
}
}
.. 然后调用 .Sort();
上述方法比重新创建整个项目源有很大优势 - 您的用户界面可以以漂亮的方式对此做出反应(项目移动的动画而不是重新创建 "blink")