2009-06-15 19 views
20

Ich habe eine beobachtbare Sammlung und ich sortiere es mit linq. Alles ist großartig, aber das Problem, das ich habe, ist, wie sortiere ich die tatsächlich beobachtbare Sammlung? Stattdessen lande ich nur mit einem IEnumerable-Ding, und am Ende erledige ich die Sammlung und füge die Sachen wieder hinzu. Das kann nicht gut für die Leistung sein. Kennt jemand einen besseren Weg, dies zu tun?Sortierung einer beobachtbaren Sammlung mit linq

+0

Mögliche Duplikat von [Sortieren ObservableCollection C#] (http://stackoverflow.com/questions/19112922/sort-observablecollectionstring-c-sharp) –

Antwort

15

Wenn Sie Silverlight 3.0 verwenden, dann mit Collection ist der sauberste Weg. Siehe unten Beispiel: (es kann auch über XAML erfolgen)

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; 

Und in entsprechendem XAML gesetzt

ItemsSource="{Binding}" 

für die List-Box oder ein beliebiges Item abgeleiteten Steuer

3

Beachten Sie, dass Sie in Linq einen IEnumerable aus Ihrer Abfrage erhalten, und diese Abfrage noch nicht ausgeführt hat. Daher läuft der folgende Code nur die Abfrage einmal, um es zu einem ObservableCollection hinzuzufügen:

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

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

Werfen Sie einen Blick auf die „OrderBy“ Erweiterung auf IEnumerable:

foreach(var item in query.OrderBy(x => x.Name)) 
    MyObservableCollection.Add(item); 
+0

Ich habe diese als Basis für etwas ähnliches für meine Code. Ich fange an zu denken, Linq ist ziemlich kick-ass :) – djcouchycouch

+0

Ich bin mir nicht sicher, wie gut das funktionieren würde, wenn Sie die ObservableCollection aus dem WCF-Dienst erhalten, einen Ratschlag? Muss ich eine neue ObservableCollection auf dem Client erstellen und "OrderBy" darauf anwenden? - Vielen Dank. – VoodooChild

+0

@VoodooChild: Wenn Sie bereits eine ObservableCollection statt nur IEnumerable haben, dann schauen Sie sich die SO-Frage an: http://StackOverflow.com/Questions/996126/Sorting-an-Observable-Collection-with-linq –

8

Da die Sammlung nicht der Fall ist stellen Sie einen Sort Mechanismus, das ist wahrscheinlich die praktischste Option. Sie könnten eine Sortierung manuell mit Move usw. implementieren, aber es wird wahrscheinlich langsamer als auf diese Weise.

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

Zusätzlich können Sie UI-Elemente freibleibend betrachten, während Sortierung (entweder über approach) nur einmal neu zu binden bezahlen:

Interessanter wenn diese BindingList<T> war, konnte man RaiseListChangedEvents verwenden die minimieren Anzahl der Benachrichtigungen:

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(); 
    } 
+0

Ich habe es gefunden hilfreich, danke! – Masha

+0

Wenn Sie diesen Weg gehen, würde ich für die Leistung 'var ordered = list.OrderBy (x => x.SomeProp); list.Clear(); list.AddRange (ordered); 'Sie vermeiden die unnötige Iteration und Ausführung von ToArray() und tun dies nur einmal während AddRange(). (Ich müsste dies dekompilieren, da AddRange ein IEnumerable-Objekt verwendet, es kann das aber auch einfach speichern, ohne es auszuführen, und dann die abgeflachte Sammlung ausführen und speichern, bevor irgendwelche listspezifischen Operationen aufgerufen werden. Gleiche Leistung am Ende, aber es verschiebt den Zyklus-Treffer nur bis später.) – JoeBrockhaus

3

ObservableCollections sind nicht sortierbar. Liste ist sortierbar, und das ist der zugrundeliegende Mechanismus, der von der Antwort verwendet wird, die auf List.Sort() verweist, aber ObservableCollection wird nicht von List abgeleitet, so dass Sie kein Glück haben. Imo, die "richtige" Lösung ist nicht zu versuchen, die ObservableCollection zu sortieren, sondern ICollectionView zu implementieren und eine Instanz davon an Ihr Steuerelement zu binden. Diese Schnittstelle fügt Methoden zum Sortieren hinzu und hat den zusätzlichen Vorteil, dass sie von Silverlight-Steuerelementen erkannt wird (naja, die, die es trotzdem unterstützen, wie DataGrid), damit Ihre Sortierung direkt von der UI-Ebene aus genutzt werden kann. Diese Frage könnte hilfreich sein:

Silverlight and icollectionview

0

i folgte den Link erwähnte in diesem Beitrag http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75

aber mit Probleme bekommen es in Silverlight

arbeiten

Ich habe eine Eigenschaft public SortableObservableCollection Terms Wenn ich Terms.Sort (neu TermComparer()) die Aufzeichnungen noch unsortiert

auf der Benutzeroberfläche angezeigt werden rufen

könnte einige vorschlagen, was schief gehen könnte.Dank

+0

Sie müssen ein Eigenschaft geändertes Ereignis in der Terms-Eigenschaft auslösen – Jack

Verwandte Themen