web-dev-qa-db-ja.com

観察可能なコレクションをlinqで並べ替える

監視可能なコレクションがあり、linqを使用して並べ替えています。すべてが素晴らしいですが、私が抱えている問題は、実際の観察可能なコレクションをどのようにソートするかです。代わりに、IEnumerableが発生し、コレクションをクリアして、それらを追加し直すことになります。これは、パフォーマンスには良くありません。誰かがこれを行うためのより良い方法を知っていますか?

20
zachary

Silverlight 3.0を使用している場合は、CollectionViewSourceを使用するのが最もクリーンな方法です。以下の例を参照してください:(xamlを介して実行することもできます)

ObservableCollection<DateTime> ecAll = new ObservableCollection<DateTime>();
CollectionViewSource sortedcvs = new CollectionViewSource();
sortedcvs.SortDescriptions.Add(new System.ComponentModel.SortDescription("Date", 
    System.ComponentModel.ListSortDirection.Ascending));
sortedcvs.Source = ecAll;
ListBoxContainer.DataContext = sortedcvs;

そして対応するxamlセットで

ItemsSource="{Binding}"

listBoxまたはItemsControl派生コントロールの場合

15
moonlightdock

コレクションはSortメカニズムを提供しないため、これがおそらく最も実用的なオプションです。 Moveなどを使用して手動で並べ替えを実装することもできますが、この方法よりもおそらく遅くなります。

    var arr = list.OrderBy(x => x.SomeProp).ToArray();
    list.Clear();
    foreach (var item in arr) {
        list.Add(item);
    }

さらに、並べ替え中にUI要素のバインドを解除することを検討することもできます(どちらの方法でも)。

興味深いことに、これがBindingList<T>RaiseListChangedEventsを使用して、通知の数を最小限に抑えることができます。

    var arr = list.OrderBy(x => x).ToArray();
    bool oldRaise = list.RaiseListChangedEvents;
    list.RaiseListChangedEvents = false;
    try {
        list.Clear();
        foreach (var item in arr) {
            list.Add(item);
        }
    } finally {
        list.RaiseListChangedEvents = oldRaise;
        if (oldRaise) list.ResetBindings();
    }
9
Marc Gravell

Linqでは、クエリからIEnumerableが与えられ、そのクエリはまだ実行されていないことに注意してください。したがって、次のコードは、クエリを1回だけ実行して、ObservableCollectionに追加します。

var query = from x in Data
            where x.Tag == "Something"
            select x;

foreach(var item in query)
    MyObservableCollection.Add(item);

IEnumerableの " OrderBy "拡張子を見てください。

foreach(var item in query.OrderBy(x => x.Name))
    MyObservableCollection.Add(item);
3
Brian Genisio

ObservableCollectionsは、並べ替え可能になるようには設計されていません。 Listは並べ替え可能であり、これがList.Sort()を参照する回答で使用される基本的なメカニズムですが、ObservableCollectionはListから派生していないため、運が悪いことになります。 Imo、「正しい」解決策は、ObservableCollectionを並べ替えようとするのではなく、ICollectionViewを実装し、そのインスタンスをコントロールにバインドすることです。このインターフェイスは、並べ替えのメソッドを追加し、Silverlightコントロール(DataGridなどのとにかくそれをサポートするコントロール)によって認識されるという追加の利点があるため、UIレイヤーから直接並べ替えを利用できます。この質問は役立つかもしれません:

Silverlightおよびicollectionview

3
James Cadd

私はこれをCodePlexで見つけました:

ソートされたコレクション

まだ使っていません。

リック

0
rboarman

この投稿に記載されているリンクをたどりました http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75 ==

しかし、Silverlightで動作させるのに問題があります

プロパティpublicSortableObservableCollectionを作成しましたTerms.Sort(new TermComparer())を呼び出すと、レコードは引き続きUIに並べ替えられずに表示されます

何がうまくいかないのかを示唆する人もいるかもしれません。ありがとう

0
joblot