【问题标题】:Order a ObservableCollection<T> without creating a new one [duplicate]订购 ObservableCollection<T> 而不创建新的 [重复]
【发布时间】:2011-04-27 18:03:27
【问题描述】:

我有以下代码来重新订购ObservableCollection&lt;T&gt; 集合:

list = new ObservableCollection<SomeType>( list.OrderBy( c=>c.Ordinal ) );

此代码有效,但我不喜欢涉及“新”的事实。有没有一种方法可以在不创建新集合的情况下更改 ObservableCollection&lt;T&gt; 集合的内部元素顺序?

谢谢,

【问题讨论】:

  • 可以使用一个非常复杂的方法here

标签: c#


【解决方案1】:

为 Observable 集合实现自定义排序扩展方法

 public static class ObservableCollection
 {
      public static void Sort<TSource, TKey>(this ObservableCollection<TSource> source, Func<TSource, TKey> keySelector)
      {
          List<TSource> sortedList = source.OrderBy(keySelector).ToList();
          source.Clear();
          foreach (var sortedItem in sortedList)
          {
              source.Add(sortedItem);
          }
     }
 }

以上答案的灵感来自于 Jaider 先生对此question的回复

【讨论】:

    【解决方案2】:

    鉴于OrderBy 还更新了一个数组以匹配您的集合的大小以及其他几个对象,您有两个选择:

    1. 完全放弃 LINQ OrderBy,编写自己的排序,使用 Move 方法对 ObservableCollection 执行就地排序。
    2. 等到当前实现出现问题后再应用 1。

    别担心,新东西没那么可怕。 Linq 一直在做这件事。除非它是一个瓶颈,否则一切都很好。除非有令人信服的证据表明就地排序确实会加快演出速度,否则这里没有问题。

    【讨论】:

    • 特别是因为项目本身不是新的,而只是包含集合。更改集合对象也会导致 INPC 绑定刷新并显示新顺序。
    • 这样做的问题是你会失去可观察集合上的任何观察者。
    • 有些客户端(例如:Windows 应用商店应用程序)使用事件(创建、移动、删除等)为 ObservableCollection 中删除或移动的项目设置动画。重新创建 ObservableCollection 毫无意义!
    【解决方案3】:

    我的回答灵感来自bkk

     public static class ObservableCollection
        {
            public static void Sort<TSource, TKey>(this ObservableCollection<TSource> source, Func<TSource, TKey> keySelector, bool isAZ)
            {
                if (isAZ)
                {
                    List<TSource> sortedList = source.OrderBy(keySelector).ToList();
                    source.Clear();
                    foreach (var sortedItem in sortedList)
                    {
                        source.Add(sortedItem);
                    }
                }
                else
                {
                    List<TSource> sortedList = source.OrderByDescending(keySelector).ToList();
                    source.Clear();
                    foreach (var sortedItem in sortedList)
                    {
                        source.Add(sortedItem);
                    }
                }         
            }
        }
    

    用法

     _someObservableCollection.Sort(x => x.Number, false); // Where number is an simple property (non-object)
    

    【讨论】:

    • isAZ 不是很直观,但这是对@bkk 答案的改进。 +1
    • 是的,我想我会称它为descending,但其他答案都很好。
    【解决方案4】:

    据我所知,ObservableCollection 具有在集合内移动项目的方法。您应该为您的 T 型获取一个比较器,然后使用一些排序算法

    【讨论】:

    • 这是真正的答案。 ObservableCollection.Move(int,int) 可以并且应该用于实现您自己的排序算法。由于我的可观察集合不是太大,我使用选择排序来最小化对 Move 的调用,因为每个调用都会调用 CollectionChanged。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多