IT story

관찰 가능한 컬렉션을 어떻게 정렬합니까?

hot-time 2020. 8. 29. 12:45
반응형

관찰 가능한 컬렉션을 어떻게 정렬합니까?


다음 수업이 있습니다.

[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"));

Q : 키별로 어떻게 정렬합니까?


OP 편집 : 많은 사람들이 올바르게 지적했듯이 원래 답변은 동일한 컬렉션을 반환하지 않습니다 (원래 Q의 사전 부분 정렬에 더 중점을 두었습니다). 관찰 가능한 컬렉션의 정렬을 다루는 하단의 편집을 참조하십시오. 여전히 투표를 받고있는 상태로 여기에 원본이 남았습니다.

아래에서 설명하는 doSort 메소드로 linq를 사용할 수 있습니다. 빠른 코드 스 니펫 : 생성

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;
    }
}

편집하다

ObservableCollection을 반환하려면 예를 들어 this implementation을 사용하여 sortedOC에서 .ToObservableCollection호출하십시오 .

OP EDIT 옵저버 블을 정렬하고 정렬 된 동일한 객체를 반환하는 것은 확장 메서드를 사용하여 수행 할 수 있습니다. 더 큰 컬렉션의 경우 컬렉션 변경 알림 수를주의하십시오.

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

        int ptr = 0;
        while (ptr < sorted.Count)
        {
            if (!observable[ptr].Equals(sorted[ptr]))
            {
                T t = observable[ptr];
                observable.RemoveAt(ptr);
                observable.Insert(sorted.IndexOf(t), t);
            }
            else
            {
                ptr++;
            }
        }
    }

사용법 : 관찰자가있는 샘플 (단순하게 유지하기 위해 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 = "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 = 15 },
            new Person { Name = "Kim",  Age = 19 }
        };

        //what do observers see?
        observable.CollectionChanged += (o, e) => {

            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems)
                {
                    Console.WriteLine("removed {0} at index {1}", item, e.OldStartingIndex);
                }
            }

            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    Console.WriteLine("added {0} at index {1}", item, e.NewStartingIndex);
                }
            }};            

        Console.WriteLine("\nsorting items...");
        observable.Sort();
    };

위의 결과 :
인덱스 0에서 51 세
Katy
제거 인덱스 8에서 51 세 Katy 제거 인덱스 3
에서 41 세 Mary 추가 인덱스 7에서 41 세 Mary 추가 인덱스 3 에서
20
세 Jane
제거 인덱스 5에서 20 세 Jane 추가 39 세 Jim 제거 인덱스 3
에서 인덱스 6에서 39 세 Jim 추가
인덱스 4
에서 20 세 Jane 인덱스 5에서 20 세 Jane 추가

Person 클래스는 IComparable과 IEquatable을 모두 구현합니다. 후자는 발생하는 변경 알림의 수를 줄이기 위해 컬렉션의 변경을 최소화하는 데 사용됩니다.


이 간단한 확장은 저에게 아름답게 작동했습니다. 난 그냥 그 확인했다 MyObject이었다 IComparable. 정렬 방법의 관찰 컬렉션 호출 될 때 MyObjectsCompareTo의 방법은 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();

이 질문이 오래되었다는 것을 알고 있지만 인터넷 검색 중에 발생한 문제이며 여기에있는 것보다 더 나은 답변을 제공하는 관련 블로그 항목을 찾았습니다.

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

최신 정보

ObservableSortedList 코멘트 아웃 @romkyns 포인트가 자동으로 정렬 순서를 유지하고있다.

항목을 정렬 된 순서로 유지하는 관찰 가능한 컬렉션을 구현합니다. 특히, 주문 변경을 초래하는 항목 속성 변경은 올바르게 처리됩니다.

그러나 비고도 참고

관련된 인터페이스의 상대적 복잡성과 상대적으로 열악한 문서로 인해 버그가있을 수 있습니다 ( https://stackoverflow.com/a/5883947/33080 참조 ).


이 간단한 방법을 사용할 수 있습니다.

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

자세한 내용 : http://jaider.net/2011-05-04/sort-a-observablecollection/


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참조하십시오 .


위의 "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);
                }
            }
        }
    }

새 컬렉션을 반환하는 대신 ObservableCollection의 기존 인스턴스를 정렬한다는 점을 제외하면 OrderBy를 호출하는 것과 동일한 방식으로 호출합니다.

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

people.Sort(p => p.FirstName);

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

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

변형은 선택 정렬 알고리즘을 사용하여 컬렉션을 정렬하는 곳 입니다. Move메서드를 사용하여 요소를 제자리로 이동합니다 . 각 이동은 (및 속성 이름 CollectionChanged함께) 이벤트를 시작 합니다.NotifyCollectionChangedAction.MovePropertyChangedItem[]

이 알고리즘에는 몇 가지 좋은 속성이 있습니다.

  • 알고리즘은 안정적인 정렬로 구현 될 수 있습니다.
  • 컬렉션에서 이동 된 항목 수 (예 : CollectionChanged발생한 이벤트)는 거의 항상 삽입 정렬 및 버블 정렬과 같은 다른 유사한 알고리즘보다 적습니다.

알고리즘은 아주 간단합니다. 컬렉션은 컬렉션의 시작 부분으로 이동되는 가장 작은 요소를 찾기 위해 반복됩니다. 이 프로세스는 모든 요소가 제자리로 이동할 때까지 두 번째 요소부터 반복됩니다. 알고리즘은 그다지 효율적이지는 않지만 사용자 인터페이스에 표시하려는 모든 것에 대해서는 중요하지 않습니다. 그러나 이동 작업의 수 측면에서 상당히 효율적입니다.

다음은 단순화를 위해 요소가 IComparable<T>. 다른 옵션은 IComparer<T>또는 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();

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

컬렉션을 항상 정렬해야합니까? 쌍을 검색 할 때 항상 정렬해야합니까? 아니면 몇 번만 수행해야합니까 (아마도 발표 용일 수도 있음)? 컬렉션이 얼마나 클 것으로 예상하십니까? 사용할 마녀 방법을 결정하는 데 도움이 될 수있는 많은 요소가 있습니다.

컬렉션을 항상 정렬해야한다면 요소를 삽입하거나 삭제하고 삽입 속도가 문제가되지 않는 경우 SortedObservableCollection에도 @Gerrie Schenck가 언급 한 것과 같은 종류를 구현 하거나이 구현을 확인 해야 합니다.

컬렉션을 몇 번만 정렬해야하는 경우 다음을 사용하세요.

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

컬렉션을 정렬하는 데 시간이 좀 걸리지 만 그래도 작업에 따라 가장 좋은 솔루션이 될 수 있습니다.


내 현재 답변은 이미 가장 많은 표를 얻었지만 더 좋고 더 현대적인 방법을 찾았습니다.

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

새 클래스를 만들고 SortedObservableCollection파생 ObservableCollection하고 구현 IComparable<Pair<ushort, string>>합니다.


한 가지 방법은 목록으로 변환 한 다음 Sort ()를 호출하여 비교 대리자를 제공하는 것입니다. 같은 것 :-

(미정)

my_collection.ToList().Sort((left, right) => left == right ? 0 : (left > right ? -1 : 1));

이것이 가장 우아한 해결책이라고 생각합니다.

http://www.xamlplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx


도대체, 나는 신속하게 함께 대답을 던질 것입니다 ... 여기에 다른 구현과 약간 비슷해 보이지만 누구에게나 추가 할 것입니다.

(간신히 테스트 됨, 바라건대 나는 내 자신을 부끄럽게하지 않습니다)

먼저 몇 가지 목표를 설명하겠습니다 (내 가정).

1) ObservableCollection<T>알림 등을 유지하기 위해 제자리에 정렬해야합니다 .

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
    }
}

이 답변 중 어느 것도 제 경우에는 효과가 없었습니다. 바인딩을 망쳐 놓거나 너무 많은 추가 코딩이 필요하기 때문에 일종의 악몽이거나 대답이 깨졌습니다. 그래서 여기에 내가 생각한 또 다른 간단한 대답이 있습니다. 코드가 훨씬 적고 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은 내 공개 클래스입니다. 훨씬 간단 해 보였습니다. 추가 된 이점 : 실제로 작동하며 바인딩을 엉망으로 만들거나 새 컬렉션 등을 반환하지 않습니다.


좋습니다 . 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에서 작동합니다.


이것이 내가 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);
        }
    }

이것은 나를 위해 일했으며 오래 전에 어딘가에서 발견했습니다.

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

하나가 아닌 여러 가지로 정렬 할 수 있어야했습니다. 이 답변은 다른 답변 중 일부를 기반으로하지만 더 복잡한 정렬이 가능합니다.

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

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

참고 URL : https://stackoverflow.com/questions/1945461/how-do-i-sort-an-observable-collection

반응형