104

我有以下课程:

[DataContract]
public class Pair<TKey, TValue> : INotifyPropertyChanged, IDisposable
{
    public Pair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }

    #region Properties
    [DataMember]
    public TKey Key
    {
        get
        { return m_key; }
        set
        {
            m_key = value;
            OnPropertyChanged("Key");
        }
    }
    [DataMember]
    public TValue Value
    {
        get { return m_value; }
        set
        {
            m_value = value;
            OnPropertyChanged("Value");
        }
    }
    #endregion

    #region Fields
    private TKey m_key;
    private TValue m_value;
    #endregion

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    #endregion

    #region IDisposable Members

    public void Dispose()
    { }

    #endregion
}

我放入了 ObservableCollection :

ObservableCollection<Pair<ushort, string>> my_collection = 
    new ObservableCollection<Pair<ushort, string>>();

my_collection.Add(new Pair(7, "aaa"));
my_collection.Add(new Pair(3, "xey"));
my_collection.Add(new Pair(6, "fty"));

问:如何按键排序?

4

22 回答 22

92

这个简单的扩展对我来说效果很好。我只需要确保那MyObjectIComparable. 当对 的可观察集合调用 sort 方法时,会调用 on方法MyObjects,该CompareTo方法MyObject调用我的逻辑排序方法。虽然它没有这里发布的其他答案的所有花里胡哨,但这正是我所需要的。

static class Extensions
{
    public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable
    {
        List<T> sorted = collection.OrderBy(x => x).ToList();
        for (int i = 0; i < sorted.Count(); i++)
            collection.Move(collection.IndexOf(sorted[i]), i);
    }
}

public class MyObject: IComparable
{
    public int CompareTo(object o)
    {
        MyObject a = this;
        MyObject b = (MyObject)o;
        return Utils.LogicalStringCompare(a.Title, b.Title);
    }

    public string Title;

}
  .
  .
  .
myCollection = new ObservableCollection<MyObject>();
//add stuff to collection
myCollection.Sort();
于 2013-05-02T18:13:58.037 回答
39

我找到了一个相关的博客条目,它提供了比这里更好的答案:

http://kiwigis.blogspot.com/2010/03/how-to-sort-obversablecollection.html

更新

@romkyns 在评论中指出的ObservableSortedList会自动维护排序顺序。

实现一个可观察的集合,该集合按排序顺序维护其项目。特别是,对导致订单更改的项目属性的更改得到正确处理。

但是还要注意这句话

由于所涉及接口的相对复杂性及其相对较差的文档(请参阅https://stackoverflow.com/a/5883947/33080),可能会出现错误。

于 2011-03-23T06:12:21.127 回答
28

您可以使用这个简单的方法:

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

你可以这样排序:

_collection.Sort(i => i.Key);
于 2011-05-04T21:35:33.880 回答
23

可以使用扩展方法对 observable 进行排序并返回已排序的相同对象。对于较大的集合,请注意集合更改通知的数量。

我已经更新了我的代码以提高性能(感谢 nawfal)并处理在撰写本文时这里没有其他答案的重复项。observable 被划分为左排序的一半和右未排序的一半,每次最小项(如在排序列表中找到的)从未排序的部分移动到排序分区的末尾。最坏情况 O(n)。本质上是一个选择排序(见下文输出)。

public static void Sort<T>(this ObservableCollection<T> collection)
        where T : IComparable<T>, IEquatable<T>
    {
        List<T> sorted = collection.OrderBy(x => x).ToList();

        int ptr = 0;
        while (ptr < sorted.Count - 1)
        {
            if (!collection[ptr].Equals(sorted[ptr]))
            {
                int idx = search(collection, ptr+1, sorted[ptr]);
                collection.Move(idx, ptr);
            }
            
            ptr++;
        }
    }

    public static int search<T>(ObservableCollection<T> collection, int startIndex, T other)
            {
                for (int i = startIndex; i < collection.Count; i++)
                {
                    if (other.Equals(collection[i]))
                        return i;
                }
    
                return -1; // decide how to handle error case
            }

用法:带有观察者的示例(使用 Person 类来保持简单)

    public class Person:IComparable<Person>,IEquatable<Person>
            { 
                public string Name { get; set; }
                public int Age { get; set; }
    
                public int CompareTo(Person other)
                {
                    if (this.Age == other.Age) return 0;
                    return this.Age.CompareTo(other.Age);
                }
    
                public override string ToString()
                {
                    return Name + " aged " + Age;
                }
    
                public bool Equals(Person other)
                {
                    if (this.Name.Equals(other.Name) && this.Age.Equals(other.Age)) return true;
                    return false;
                }
            }
    
          static void Main(string[] args)
            {
                Console.WriteLine("adding items...");
                var observable = new ObservableCollection<Person>()
                {
                    new Person {Name = "Katy", Age = 51},
                    new Person {Name = "Jack", Age = 12},
                    new Person {Name = "Bob", Age = 13},
                    new Person {Name = "Alice", Age = 39},
                    new Person {Name = "John", Age = 14},
                    new Person {Name = "Mary", Age = 41},
                    new Person {Name = "Jane", Age = 20},
                    new Person {Name = "Jim", Age = 39},
                    new Person {Name = "Sue", Age = 5},
                    new Person {Name = "Kim", Age = 19}
                };
    
                //what do observers see?
            
    
observable.CollectionChanged += (sender, e) =>
        {
            Console.WriteLine(
                e.OldItems[0] + " move from " + e.OldStartingIndex + " to " + e.NewStartingIndex);
            int i = 0;
            foreach (var person in sender as ObservableCollection<Person>)
            {
                if (i == e.NewStartingIndex)
                {
                    Console.Write("(" + (person as Person).Age + "),");
                }
                else
                {
                    Console.Write((person as Person).Age + ",");
                }
                
                i++;
            }

            Console.WriteLine();
        };

显示集合如何旋转的排序进度的详细信息:

Sue aged 5 move from 8 to 0
(5),51,12,13,39,14,41,20,39,19,
Jack aged 12 move from 2 to 1
5,(12),51,13,39,14,41,20,39,19,
Bob aged 13 move from 3 to 2
5,12,(13),51,39,14,41,20,39,19,
John aged 14 move from 5 to 3
5,12,13,(14),51,39,41,20,39,19,
Kim aged 19 move from 9 to 4
5,12,13,14,(19),51,39,41,20,39,
Jane aged 20 move from 8 to 5
5,12,13,14,19,(20),51,39,41,39,
Alice aged 39 move from 7 to 6
5,12,13,14,19,20,(39),51,41,39,
Jim aged 39 move from 9 to 7
5,12,13,14,19,20,39,(39),51,41,
Mary aged 41 move from 9 to 8
5,12,13,14,19,20,39,39,(41),51,

Person 类同时实现了 IComparable 和 IEquatable 后者用于最小化对集合的更改,从而减少引发的更改通知的数量

  • EDIT 对同一集合进行排序而不创建新副本 *

要返回 ObservableCollection,请使用例如 [this implementation][1] 在 *sortedOC* 上调用 .ToObservableCollection。

**** orig answer - 这将创建一个新集合**** 您可以使用 linq,如下面的 doSort 方法所示。一个快速的代码片段:产生

3:xey 6:fty 7:aaa

或者,您可以在集合本身上使用扩展方法

var sortedOC = _collection.OrderBy(i => i.Key);

private void doSort()
{
    ObservableCollection<Pair<ushort, string>> _collection = 
        new ObservableCollection<Pair<ushort, string>>();

    _collection.Add(new Pair<ushort,string>(7,"aaa"));
    _collection.Add(new Pair<ushort, string>(3, "xey"));
    _collection.Add(new Pair<ushort, string>(6, "fty"));

    var sortedOC = from item in _collection
                   orderby item.Key
                   select item;

    foreach (var i in sortedOC)
    {
        Debug.WriteLine(i);
    }

}

public class Pair<TKey, TValue>
{
    private TKey _key;

    public TKey Key
    {
        get { return _key; }
        set { _key = value; }
    }
    private TValue _value;

    public TValue Value
    {
        get { return _value; }
        set { _value = value; }
    }
    
    public Pair(TKey key, TValue value)
    {
        _key = key;
        _value = value;

    }

    public override string ToString()
    {
        return this.Key + ":" + this.Value;
    }
}
于 2009-12-22T11:07:31.293 回答
20

WPF使用类提供开箱即用的实时排序ListCollectionView...

public ObservableCollection<string> MyStrings { get; set; }
private ListCollectionView _listCollectionView;
private void InitializeCollection()
{
    MyStrings = new ObservableCollection<string>();
    _listCollectionView = CollectionViewSource.GetDefaultView(MyStrings) 
              as ListCollectionView;
    if (_listCollectionView != null)
    {
        _listCollectionView.IsLiveSorting = true;
        _listCollectionView.CustomSort = new 
                CaseInsensitiveComparer(CultureInfo.InvariantCulture);
    }
}

一旦这个初始化完成,就没有什么可做的了。与被动排序相比的优势在于 ListCollectionView 以对开发人员透明的方式完成所有繁重的工作。新项目会自动按正确的排序顺序放置。任何派生自IComparerT 的类都适用于自定义排序属性。

有关文档和其他功能,请参阅ListCollectionView

于 2016-06-04T19:36:33.573 回答
15

我喜欢上面“Richie”博客上的冒泡排序扩展方法方法,但我不一定只想对整个对象进行排序比较。我更经常想对对象的特定属性进行排序。因此,我对其进行了修改,以像 OrderBy 那样接受一个键选择器,这样您就可以选择要排序的属性:

    public static void Sort<TSource, TKey>(this ObservableCollection<TSource> source, Func<TSource, TKey> keySelector)
    {
        if (source == null) return;

        Comparer<TKey> comparer = Comparer<TKey>.Default;

        for (int i = source.Count - 1; i >= 0; i--)
        {
            for (int j = 1; j <= i; j++)
            {
                TSource o1 = source[j - 1];
                TSource o2 = source[j];
                if (comparer.Compare(keySelector(o1), keySelector(o2)) > 0)
                {
                    source.Remove(o1);
                    source.Insert(j, o1);
                }
            }
        }
    }

您可以像调用 OrderBy 一样调用它,只是它会对 ObservableCollection 的现有实例进行排序,而不是返回一个新集合:

ObservableCollection<Person> people = new ObservableCollection<Person>();
...

people.Sort(p => p.FirstName);
于 2012-06-11T18:02:38.817 回答
12

@NielW 的答案是真正的就地排序。我想添加一个稍微改变的解决方案,让您绕过必须使用IComparable

static class Extensions
{
    public static void Sort<TSource, TKey>(this ObservableCollection<TSource> collection, Func<TSource, TKey> keySelector)
    {
        List<TSource> sorted = collection.OrderBy(keySelector).ToList();
        for (int i = 0; i < sorted.Count(); i++)
            collection.Move(collection.IndexOf(sorted[i]), i);
    }
}

现在您可以像大多数 LINQ 方法一样调用它:

myObservableCollection.Sort(o => o.MyProperty);
于 2015-07-27T16:56:12.203 回答
11

我想添加到 NeilW 的答案中。合并一个类似于 orderby 的方法。将此方法添加为扩展:

public static void Sort<T>(this ObservableCollection<T> collection, Func<T,T> keySelector) where T : IComparable
{
    List<T> sorted = collection.OrderBy(keySelector).ToList();
    for (int i = 0; i < sorted.Count(); i++)
        collection.Move(collection.IndexOf(sorted[i]), i);
}

并使用如下:

myCollection = new ObservableCollection<MyObject>();

//Sorts in place, on a specific Func<T,T>
myCollection.Sort(x => x.ID);
于 2015-03-21T09:02:42.680 回答
8

一种变体是使用选择排序算法对集合进行就地排序。Move使用该方法将元素移动到位。每次移动都会触发CollectionChanged事件NotifyCollectionChangedAction.Move(以及PropertyChanged属性 name Item[])。

这个算法有一些很好的特性:

  • 该算法可以实现为稳定排序。
  • 在集合中移动的项目数(例如CollectionChanged触发的事件)几乎总是少于其他类似的算法,如插入排序和冒泡排序。

该算法非常简单。迭代集合以找到最小的元素,然后将其移动到集合的开头。从第二个元素开始重复该过程,依此类推,直到所有元素都已移动到位。该算法效率不是很高,但对于您要在用户界面中显示的任何内容,它都无关紧要。但是,就移动操作的数量而言,它非常有效。

这是一个扩展方法,为简单起见,要求元素实现IComparable<T>. 其他选项使用 aIComparer<T>或 a Func<T, T, Int32>

public static class ObservableCollectionExtensions {

  public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable<T> {
    if (collection == null)
      throw new ArgumentNullException("collection");

    for (var startIndex = 0; startIndex < collection.Count - 1; startIndex += 1) {
      var indexOfSmallestItem = startIndex;
      for (var i = startIndex + 1; i < collection.Count; i += 1)
        if (collection[i].CompareTo(collection[indexOfSmallestItem]) < 0)
          indexOfSmallestItem = i;
      if (indexOfSmallestItem != startIndex)
        collection.Move(indexOfSmallestItem, startIndex);
    }
  }

}

对集合进行排序只是调用扩展方法的问题:

var collection = new ObservableCollection<String>(...);
collection.Sort();
于 2013-01-17T02:26:58.720 回答
4

为了稍微改进 xr280xr 答案上的扩展方法,我添加了一个可选的 bool 参数来确定排序是否为降序。我还在对该答案的评论中包含了 Carlos P 提出的建议。请看下文。

public static void Sort<TSource, TKey>(this ObservableCollection<TSource> source, Func<TSource, TKey> keySelector, bool desc = false)
    {
        if (source == null) return;

        Comparer<TKey> comparer = Comparer<TKey>.Default;

        for (int i = source.Count - 1; i >= 0; i--)
        {
            for (int j = 1; j <= i; j++)
            {
                TSource o1 = source[j - 1];
                TSource o2 = source[j];
                int comparison = comparer.Compare(keySelector(o1), keySelector(o2));
                if (desc && comparison < 0)
                    source.Move(j, j - 1);
                else if (!desc && comparison > 0)
                    source.Move(j - 1, j);
            }
        }
    }
于 2012-09-22T00:37:00.870 回答
2

您是否需要始终对您的收藏进行分类?检索对时,您是否需要始终对它们进行排序,或者只进行几次排序(可能只是为了呈现)?你希望你的收藏有多大?有很多因素可以帮助您决定使用女巫方法。

如果您需要始终对集合进行排序,即使您插入或删除元素并且插入速度不是问题,也许您应该实现某种SortedObservableCollection类似@Gerrie Schenck 提到的或查看此实现

如果您需要对您的收藏品进行几次分类,请使用:

my_collection.OrderBy(p => p.Key);

这将需要一些时间来对集合进行排序,但即便如此,它可能是最好的解决方案,具体取决于您对它的处理方式。

于 2009-12-22T11:10:05.137 回答
2

我目前的答案已经获得了最多的选票,但我找到了一种更好、更现代的方法。

class MyObject 
{
      public int id { get; set; }
      public string title { get; set; }
}

ObservableCollection<MyObject> myCollection = new ObservableCollection<MyObject>();

//add stuff to collection
// .
// .
// .

myCollection = new ObservableCollection<MyObject>(
    myCollection.OrderBy(n => n.title, Comparer<string>.Create(
    (x, y) => (Utils.Utils.LogicalStringCompare(x, y)))));
于 2016-09-07T16:07:18.180 回答
1

创建一个新类SortedObservableCollection,从中派生ObservableCollection并实现它IComparable<Pair<ushort, string>>

于 2009-12-22T10:24:27.490 回答
1

一种方法是将其转换为 List,然后调用 Sort(),提供比较委托。就像是:-

(未经测试)

my_collection.ToList().Sort((left, right) => left == right ? 0 : (left > right ? -1 : 1));
于 2009-12-22T11:13:00.730 回答
1

到底是什么,我也会给出一个快速拼凑的答案......它看起来有点像这里的一些其他实现,但我会添加它任何人:

(几乎没有测试过,希望我不会让自己尴尬)

让我们先说明一些目标(我的假设):

ObservableCollection<T>1) 必须就地排序,维护通知等。

2) 不能非常低效(即接近标准的“好”分拣效率)

public static class Ext
{
    public static void Sort<T>(this ObservableCollection<T> src)
        where T : IComparable<T>
    {
        // Some preliminary safety checks
        if(src == null) throw new ArgumentNullException("src");
        if(!src.Any()) return;

        // N for the select,
        // + ~ N log N, assuming "smart" sort implementation on the OrderBy
        // Total: N log N + N (est)
        var indexedPairs = src
            .Select((item,i) => Tuple.Create(i, item))
            .OrderBy(tup => tup.Item2);
        // N for another select
        var postIndexedPairs = indexedPairs
            .Select((item,i) => Tuple.Create(i, item.Item1, item.Item2));
        // N for a loop over every element
        var pairEnum = postIndexedPairs.GetEnumerator();
        pairEnum.MoveNext();
        for(int idx = 0; idx < src.Count; idx++, pairEnum.MoveNext())
        {
            src.RemoveAt(pairEnum.Current.Item1);
            src.Insert(idx, pairEnum.Current.Item3);            
        }
        // (very roughly) Estimated Complexity: 
        // N log N + N + N + N
        // == N log N + 3N
    }
}
于 2013-03-26T15:39:25.800 回答
1

这些答案都不适用于我的情况。要么是因为它搞砸了绑定,要么是因为它需要太多额外的编码以至于它是一场噩梦,或者答案只是被打破了。所以,这是我认为的另一个更简单的答案。它的代码少了很多,并且它仍然是相同的可观察集合,并带有一个额外的 this.sort 类型的方法。让我知道是否有某些原因我不应该这样做(效率等)?

public class ScoutItems : ObservableCollection<ScoutItem>
{
    public void Sort(SortDirection _sDir, string _sItem)
    {
             //TODO: Add logic to look at _sItem and decide what property to sort on
            IEnumerable<ScoutItem> si_enum = this.AsEnumerable();

            if (_sDir == SortDirection.Ascending)
            {
                si_enum = si_enum.OrderBy(p => p.UPC).AsEnumerable();
            } else
            {
                si_enum = si_enum.OrderByDescending(p => p.UPC).AsEnumerable();
            }

            foreach (ScoutItem si in si_enum)
            {
                int _OldIndex = this.IndexOf(si);
                int _NewIndex = si_enum.ToList().IndexOf(si);
                this.MoveItem(_OldIndex, _NewIndex);
            }
      }
}

... ScoutItem 是我的公开课。只是看起来简单了很多。额外的好处:它确实有效并且不会与绑定混淆或返回新集合等。

于 2013-10-12T20:48:58.880 回答
1

好的,因为我在让 ObservableSortedList 与 XAML 一起工作时遇到问题,所以我继续创建了SortingObservableCollection。它继承自 ObservableCollection,因此它可以与 XAML 一起使用,并且我已经对其进行了 98% 的代码覆盖率的单元测试。我已经在自己的应用程序中使用过它,但我不会保证它没有错误。随意贡献。这是示例代码用法:

var collection = new SortingObservableCollection<MyViewModel, int>(Comparer<int>.Default, model => model.IntPropertyToSortOn);

collection.Add(new MyViewModel(3));
collection.Add(new MyViewModel(1));
collection.Add(new MyViewModel(2));
// At this point, the order is 1, 2, 3
collection[0].IntPropertyToSortOn = 4; // As long as IntPropertyToSortOn uses INotifyPropertyChanged, this will cause the collection to resort correctly

它是一个 PCL,因此它应该适用于 Windows Store、Windows Phone 和 .NET 4.5.1。

于 2014-01-30T17:58:59.157 回答
1

这对我有用,很久以前就在某个地方找到了。

// SortableObservableCollection
public class SortableObservableCollection<T> : ObservableCollection<T>
    {
        public SortableObservableCollection(List<T> list)
            : base(list)
        {
        }

        public SortableObservableCollection()
        {
        }

        public void Sort<TKey>(Func<T, TKey> keySelector, System.ComponentModel.ListSortDirection direction)
        {
            switch (direction)
            {
                case System.ComponentModel.ListSortDirection.Ascending:
                    {
                        ApplySort(Items.OrderBy(keySelector));
                        break;
                    }
                case System.ComponentModel.ListSortDirection.Descending:
                    {
                        ApplySort(Items.OrderByDescending(keySelector));
                        break;
                    }
            }
        }

        public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
        {
            ApplySort(Items.OrderBy(keySelector, comparer));
        }

        private void ApplySort(IEnumerable<T> sortedItems)
        {
            var sortedItemsList = sortedItems.ToList();

            foreach (var item in sortedItemsList)
            {
                Move(IndexOf(item), sortedItemsList.IndexOf(item));
            }
        }
    }

用法:

MySortableCollection.Sort(x => x, System.ComponentModel.ListSortDirection.Ascending);
于 2015-10-05T13:03:45.683 回答
1

这就是我对 OC 扩展所做的事情:

    /// <summary>
    /// Synches the collection items to the target collection items.
    /// This does not observe sort order.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The items.</param>
    /// <param name="updatedCollection">The updated collection.</param>
    public static void SynchCollection<T>(this IList<T> source, IEnumerable<T> updatedCollection)
    {
        // Evaluate
        if (updatedCollection == null) return;

        // Make a list
        var collectionArray = updatedCollection.ToArray();

        // Remove items from FilteredViewItems not in list
        source.RemoveRange(source.Except(collectionArray));

        // Add items not in FilteredViewItems that are in list
        source.AddRange(collectionArray.Except(source));
    }

    /// <summary>
    /// Synches the collection items to the target collection items.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The source.</param>
    /// <param name="updatedCollection">The updated collection.</param>
    /// <param name="canSort">if set to <c>true</c> [can sort].</param>
    public static void SynchCollection<T>(this ObservableCollection<T> source,
        IList<T> updatedCollection, bool canSort = false)
    {
        // Synch collection
        SynchCollection(source, updatedCollection.AsEnumerable());

        // Sort collection
        if (!canSort) return;

        // Update indexes as needed
        for (var i = 0; i < updatedCollection.Count; i++)
        {
            // Index of new location
            var index = source.IndexOf(updatedCollection[i]);
            if (index == i) continue;

            // Move item to new index if it has changed.
            source.Move(index, i);
        }
    }
于 2015-12-12T18:08:20.067 回答
0

我需要能够按多种事物进行排序,而不仅仅是一项。该答案基于其他一些答案,但它允许进行更复杂的排序。

static class Extensions
{
    public static void Sort<T, TKey>(this ObservableCollection<T> collection, Func<ObservableCollection<T>, TKey> sort)
    {
        var sorted = (sort.Invoke(collection) as IOrderedEnumerable<T>).ToArray();
        for (int i = 0; i < sorted.Count(); i++)
            collection.Move(collection.IndexOf(sorted[i]), i);
    }
}

使用它时,传入一系列 OrderBy/ThenBy 调用。像这样:

Children.Sort(col => col.OrderByDescending(xx => xx.ItemType == "drive")
                    .ThenByDescending(xx => xx.ItemType == "folder")
                    .ThenBy(xx => xx.Path));
于 2016-11-01T14:52:59.223 回答
0

我从其他解决方案中学到了很多东西,但我发现了一些问题。首先,有些依赖于 IndexOf,这对于大型列表来说往往很慢。其次,我的 ObservableCollection 有 EF 实体,并且使用 Remove 似乎破坏了一些外键属性。也许我做错了什么。

无论如何,可以使用移动来代替删除/插入,但这会导致性能修复出现一些问题。

为了解决性能问题,我使用 IndexOf 排序值创建了一个字典。要使字典保持最新并保留实体属性,请使用通过两次移动实现的交换,而不是在其他解决方案中实现的一次。

一次移动会在位置之间移动元素的索引,这会使 IndexOf 字典无效。添加第二步以实施交换恢复位置。

public static void Sort<TSource, TKey>(this ObservableCollection<TSource> collection, Func<TSource, TKey> keySelector)
{
    List<TSource> sorted = collection.OrderBy(keySelector).ToList();
    Dictionary<TSource, int> indexOf = new Dictionary<TSource, int>();

    for (int i = 0; i < sorted.Count; i++)
        indexOf[sorted[i]] = i;

    int idx = 0;
    while (idx < sorted.Count)
        if (!collection[idx].Equals(sorted[idx])) {
            int newIdx = indexOf[collection[idx]]; // where should current item go?
            collection.Move(newIdx, idx); // move whatever's there to current location
            collection.Move(idx + 1, newIdx); // move current item to proper location
        }
        else {
            idx++;
        }
}
于 2020-05-15T08:42:49.353 回答
-3
var collection = new ObservableCollection<int>();

collection.Add(7);
collection.Add(4);
collection.Add(12);
collection.Add(1);
collection.Add(20);

// ascending
collection = new ObservableCollection<int>(collection.OrderBy(a => a));

// descending
collection = new ObservableCollection<int>(collection.OrderByDescending(a => a));
于 2013-03-18T20:03:43.970 回答