ObservableCollection(Of Class) mit LINQ nach zwei Kriterien nacheinander sortieren

  • WPF MVVM
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von loeffel.

    ObservableCollection(Of Class) mit LINQ nach zwei Kriterien nacheinander sortieren

    Hallo an alle :)

    ich möchte meine Playlist, eine ObservableCollection, zuerst nach Alben, dann hinterher nach Tracknummern sortieren (jeweils Properties meiner Klasse). Leider schein es da ein Problem mit dem Typ der Auflistung zu geben:

    VB.NET-Quellcode

    1. ​Playlist = CType(Playlist.OrderBy(Function(x) x.Album).ThenBy(Function(x) x.Tracknummer), ObservableCollection(Of MP3FileInfoVM))


    Fehlermeldung:
    Das Objekt des Typs "System.Linq.OrderedEnumerable`2[VamosALaPlayer_3._0.ViewModel.MP3FileInfoVM,System.String]" kann nicht in Typ "System.Collections.ObjectModel.ObservableCollection`1[VamosALaPlayer_3._0.ViewModel.MP3FileInfoVM]" umgewandelt werden.

    Bin ich da überhaupt auf dem richtigen Weg oder sollte man das anders machen. Das Thema LINQ interessiert mich schon seit längerem...
    Versuch mal …ThenBy().ToList() und das dann ggf. Casten
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    OrderBy/ThenBy liefern eine Collection vom Typ IOrderedEnumerable zurueck. Das Interface ist quasi ein Zeiger auf eine Auflistung, die deine Elemente in sortierter Form haelt, und du kannst sie aber nicht direkt zurueck in eine ObservableCollection casten, weil die Typen nicht "kompatibel" sind.

    Aus dem Kopf:
    Ein Ansatz ist es, eine neue ObservableCollection zu instanziieren, den Konstruktor derselben mit dem Ergebnis deiner Query zu fuettern und dann diese Collection zurueck an Playlist zuzuweisen.
    @mrMo

    Ja das war auch mein erster Gedanke, da hat er aber wieder andere Probleme mit der Umwandlung (List zu OC)

    @loeffel
    Ich steig da momentan nicht so ganz dahinter, wie du das Ergebnis der Query einspeisen willst. Meine Klasse hat schon nen Konstruktor, der nimmt die Properties einzeln als Argumente an...

    @Akanel
    Kommt drauf an, was du mit weiter arbeiten meinst... Ja es gibt noch andere Ereignisse, die auftreten können, um die Datensätze zu ändern/löschen/umsortieren usw...
    In etwa so (wobei ich in VB anders als in C#, bei dem ich wie in deinem Beispiel Extension Methods verwende, immer gerne die VB LINQ Syntax benutze):

    VB.NET-Quellcode

    1. PlayList = New ObservableCollection(Of MP3FileInfoVM)(From mp3FileItems In PlayList
    2. Order By mp3FileItems.Album, mp3FileItems.TrackNummer)

    kafffee schrieb:

    ich möchte meine Playlist, eine ObservableCollection, zuerst nach Alben, dann hinterher nach Tracknummern sortieren

    Wenn es um eine sortierte Anzeige geht, kommt vlt. ein ListCollectionView infrage. Daran kann man einerseits gut binden, andererseits kann man über SortDescriptions Sortierungen angeben.
    Das scheint so ein Pattern der Datenverarbeitung zu sein, dass man für Sortieren, Filtern und SelectionManagement die eigentlichen Daten garnet anfasst, sondern datengebundene "Sichten" zwischenschiebt.
    Genau das war mein Gedanke @ErfinderDesRades

    C#-Quellcode

    1. private ObservableCollection<MP3FileInfoVm> _playlist;
    2. public ObservableCollection<MP3FileInfoVm> Playlist
    3. {
    4. get { return _playlist; }
    5. set {_playlist = value; RaisePropertyChanged(); }
    6. }
    7. private ICollectionView _playlistView;
    8. public ICollectionView PlaylistView
    9. {
    10. get { return _playlistView; }
    11. set { _playlistView = value; RaisePropertyChanged(); }
    12. }
    13. public DeinViewmodel()
    14. {
    15. PlaylistView.CollectionViewSource.GetDefaultView(Playlist);
    16. playlistView.Sortcollections.Add(new Sortcollection(„Album“, ListSortDirection.Ascending));
    17. }


    So in der Art?
    Wieder vom Handy geschrieben, können Schreibfehler drin sein.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Akanel“ ()

    Jo, der Code wird wohl so nicht aufgehen.
    Hier habich vergleichbares vor kurzem auch schon vorgeturnt: DataGrid c#
    Ich mag ja generell diesen Interface-Fimmel nicht: Wenn klar ist, dasses eine ListCollectionView ist, und ich an der Stelle auch eine ListCollectionview brauche - warum sollte ich sie dann in einer ICollectionView-Variable lagern, wo zB die SortDescriptions nicht verfügbar sind?

    Und meine ListCollectionView-Properties bekommen auch keinen Setter und kein NotifyPropertyChanged.
    Es ist nicht vorgesehen (weil es verheerend wäre), die eine ListCollectionView im Viewmodel durch eine andere ListCollectionView zu ersetzen. (Die Daten sind für Änderungen vorgesehen, aber die View selbst bleibt immer dieselbe).
    Ja und für was nicht vorgesehen ist - weil es schädlich wäre - stelle ich natürlich auch keinen Setter bereit.
    @loeffel
    Spitze, genauso hatte ich mir das vorgestellt. Diese Schreibweise war mir unbekannt (das mit dem zweiten Paar Klammern). Gibts das irgendwo zum Nachlesen?

    @Akanel
    @ErfinderDesRades

    Jou wie immer vielen Dank. Meine Playlist ist an ein DataGrid gebunden, da kann ich ja durch Klick auf die ColumnHeader nach jeder beliebigen Spalte sortieren, wenn es nur ums Anzeigen geht. Nur nach zwei Kriterien sortieren, das wär mir neu. Lass mich aber gern eines Besseren belehren. Ich brauch mein Binding DataGrid<>Playlist als TwoWay, denn ich hab so eine Klasse drin, die mir das Verschieben (in der View) der einzelnen Zeilen ermöglicht...
    Das zweite Klammerpaar ist lediglich der Parameter fuer den Konstruktor von ObservableCollection.
    Der ist ueberladen. Es gibt einen Standardkonstruktor. Und dann einen Parameter, der eine IEnumerable vom selben generischen Typen nimmt. IOrderedEnumerable ist abgeleitet von IEnumerable, deswegen erfullt der Type des Konstruktorparameter die Voraussetzungen. Das ist schon alles.

    Etwas im Hinterkopf zu behalten: Die alte Collection wird weggeworfen, und die neue aufgebaut. Aber: Das betrifft nur die Zeiger auf die vorhandenen Elemente-Instanzen, nicht die Elemente Instanzen selbst - insofern wird man im Grunde damit leben koennen.