2011-01-12 4 views
3

Im Grunde habe ich eine KeyedCollection<string, CustomNode> bekam, und ich möchte die Taste, um die Sammlung sortieren können (oder vorzugsweise mit einem benutzerdefinierten Vergleich).Wie sortieren Sie eine KeyedCollection <TKey, TItem>?

Wenn dies nicht möglich ist, kann jemand eine andere Klasse empfehlen, wo der Schlüssel im Wert eingebettet ist, dass ich sortieren?

+0

Sie geben den Schlüssel (string) kann sich ändern, so dass es nicht schwer statischer Schlüssel. Wenn die Daten keinen klassischen Schlüssel haben, verwenden Sie keinen Schlüssel, keine Wertauflistung (selbst wenn der Schlüssel von einem Wert abgeleitet ist). Ich würde einfach eine Liste verwenden und LINQ zum Sortieren verwenden. Wenn der Schlüssel geändert wird, hat die mycollection [Schlüssel] nicht so viel Dienstprogramm und wird eine Ausnahme auslösen, wenn der Schlüssel nicht gefunden wird. An diesem Punkt suchen Sie dynamische Daten und Sie können einfach LINQ verwenden. – Paparazzi

Antwort

-1

Warum nicht einfach eine SortedList<TKey, TValue> Klasse verwenden?

MSDN link

+2

Da eine KeyedCollection den Schlüsselwert ableitet, anstatt Sie explizit dazu zu zwingen. –

+2

Dies. Ich sagte, ich möchte, dass der Schlüssel eingebettet wird. – Miguel

2

KeyCollection<T> erbt von Collection<T>, die implementiert IEnumerable so sollten Sie in der Lage sein IEnumerable.OrderBy() zu verwenden. IEnumerable.OrderBy() hat auch eine Überlastung, die allows you to supply a custom comparer.

+4

OrderBy gibt eine neue Kollektion zurück, sortiert aber nicht die aktuelle Kollektion. – Miguel

-1

Sie könnten sich die SortedDictionary Sammlung ansehen ... Aber das wird mit zusätzlichen Kosten für die Artikelwiederherstellung O (log N) im Gegensatz zu einer KeyedCollection mit O (1) Abruf kommen.

+2

Eine andere Klasse *, in der der Schlüssel in den Wert eingebettet ist * – Miguel

+0

Huh? Der Schlüssel, der zum Sortieren in SortedDictionary verwendet wird, kann extern vom Element geliefert oder sogar "eingebettet" werden - das heißt, es wird beim Einfügen angegeben. – Reddog

+1

Aber von diesem Punkt an ist es getrennt von dem Wert. Wenn ich den Wert des Knotens ändere, möchte ich, dass er den Schlüssel ändert. – Miguel

2

Bei weiteren Informationen (siehe oben unter answer) ist es erforderlich, den "set" nach der Bearbeitung der Eigenschaft nach der Eigenschaft eines Elements sortiert zu halten.

In diesem Fall können Sie einen Blick auf BindableLinq werfen (es gibt auch andere ähnliche Frameworks) und verwenden Sie die dort implementierte OrderBy-Anweisung.

KeyedCollection<string, CustomNode> collection = /* from whereever */ 
collection.Items.AsBindable().OrderBy(c => c.PropertyOnCustomNode); 

Solange Ihr bearbeitetes Objekt ein Property Ereignis auslöst, dann wird es sofort die Nachbestellung anzuwenden. Wenn Sie Ihre Sammlung ändern möchten, stellen Sie sicher, dass die Quellensammlung INotifyCollectionChanged implementiert.

+0

Ordnet die AsBindable() .OrdBy() die aktuellen Elemente oder gibt ein IEnumberable der sortierten Elemente zurück? – Miguel

+0

Ja - es gibt die Elemente der Reihe nach aus, wenn sie wiederholt werden. Und ja - ich glaube, aufgrund der Tatsache, dass BindableLinq intern geschrieben ist, sollten Sie feststellen, dass es Kopien der Elemente in der Reihenfolge speichert (d. H. Vorberechnete Sortierung). Wenn Sie möchten, dass die Elemente in der Reihenfolge (in Ihrer Stammsammlung) gespeichert werden, führt dies zu meiner ursprünglichen Antwort, stattdessen ein SortedDictionary oder SortedList zu verwenden oder einen Sortieralgorithmus für Ihre Eingabesammlung aufzurufen (http: //www.codeproject .com/KB/rezepte/cssorters.aspx). – Reddog

1

auf den Link in der Antwort von Dan, sofern dies aufgrund: http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/56adc0f9-aa1b-4acf-8546-082bb01058f2/

public class RequestTemplate : IComparable<RequestTemplate> 
    { 
     // This is the primary key for the object 
     private Guid _guidNumber; 

     // This is what a collection of these objects should be sorted by 
     private string _buttonCaption = ""; 


     public Guid GuidNumber 
     { 
     get { return _guidNumber; } 
     set { _guidNumber = value; } // Setter only provided for deserialization usage 
     } 

     public string ButtonCaption 
     { 
     get { return _buttonCaption; } 
     set { _buttonCaption = value; } 
     } 


     /// <summary> 
     /// Method needed to allow sorting a collection of these objects. 
     /// </summary> 
     public int CompareTo(RequestTemplate other) 
     { 
     return string.Compare(this.ButtonCaption, other.ButtonCaption, 
           StringComparison.CurrentCultureIgnoreCase); 
     } 
    } 


    public class RequestTemplateKeyedCollection : KeyedCollection<Guid, RequestTemplate> 
    { 
     /// <summary> 
     /// Sort the collection by sorting the underlying collection, accessed by casting the Items 
     /// property from IList to List. 
     /// </summary> 
     public void Sort() 
     { 
     List<RequestTemplate> castList = base.Items as List<RequestTemplate>; 
     if (castList != null) 
      castList.Sort(); // Uses default Sort() for collection items (RequestTemplate) 
     } 


     /// <summary> 
     /// Method needed by KeyedCollection. 
     /// </summary> 
     protected override Guid GetKeyForItem(RequestTemplate requestTemplate) 
     { 
     return requestTemplate.GuidNumber; 
     } 
    } 

nicht extensiv noch nicht getestet, aber es scheint gut zu funktionieren.

Verwandte Themen