对ObservableCollection <object>进行排序不会更新UI

时间:2015-11-03 18:15:20

标签: c# linq sorting windows-runtime

我正在构建Windows Phone 8.1(WinRt)应用程序。

我有一个ObservableCollection<object>,我需要添加,修改和排序此集合的项目。

当我将一个项目添加到此列表时,一切正常,如果我在列表中投射此对象之一并编辑对象的属性INotifyPropertyChanged负责更新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,其中ItemTemplateSelector基于ObservableCollection中对象的类型,我只需要对元素进行排序特定类型。

1 个答案:

答案 0 :(得分:2)

ObservableCollection进行排序的正确方法是扩展基础ObservableCollection并使用内部CollectionChanged事件。

您当前的代码会重新创建效率低下的整个集合(并且您的用户界面可能会“闪烁”)。

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();

上述方法比重新创建整个项目源具有很大的优势 - 您的用户界面可以以相当方式对其做出反应(项目移动的动画而不是重新创建“闪烁”)