Sortierung einer DataGridViewComboBoxColumn

    • VB.NET
    • .NET (FX) 3.0–3.5

      Sortierung einer DataGridViewComboBoxColumn

      Zunächst: Der Beitrag könnte ebensogut im Bereich Controls auftauchen, den letztendlich ist ja das DataGridView betroffen. Die Lösung der Aufgabenstellung erfolgt jedoch nicht auf Control-Ebene, sonern auf Ebene einer DataTable. Daher scheint Der Bereich Datenbanken sinnvoller zu sein.

      Eine DataGridViewComboBoxColumn wird ja häufig verwendet, um die Daten einer verbundenen Tabelle im Klartext anzuzeigen.
      In Verbindung mit der im DataGridView eingebauten Sortierfunktionalität kann die entsprechende Spalte durch Mouseclick auf den Spaltenheader auch sortiert werden.
      Bedauerlicherweise erfolgt diese Sortierung dann jedoch nach den in der Tabelle enthaltenen numerischen Werten, und nicht nach dem Klartext der verbundenen Tabelle.



      Das Bild zeigt das zugrunde liegende DataSet.

      Um nun die gewünsche Funktionalität, nämlch Sortierung der DataGridView-ComboBoxColumn nach dem DisplayMember zu erreichen, wird zunächst der Spaltenkopf-Mausklick abgefangen und ausgewertet:

      VB.NET-Quellcode

      1. Private Sub SortByDisplayNameMaterialDataGridView_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) _
      2. Handles SortByDisplayNameMaterialDataGridView.ColumnHeaderMouseClick
      3. '
      4. ' Ist der MouseClick auf dem ColumnHeader der gewünschten ComboBoxColumn erfolgt?
      5. '
      6. If e.ColumnIndex = Me.IDPersonDisplayMemberComboBoxColumn.Index Then ' Mit diesem Konstrukt kann die Splate typsicher identifiziert werden.
      7. DoTheSort() ' Aufruf der für diese Spalte zuständigen Sortier-Routine
      8. End If
      9. End Sub

      Damit diese Sortierroutine auch funktioniert, muss in der zugehörigen DataGridViewComboBoxColumn SortMode = DataGridViewColumnSortMode.Programmatic eingestellt sein.
      Nun zur Sortierung (Anmerkung: Die Variablenbezeichnungen sind bewusst lang gewählt, um ihre Funktion zu beschreiben):

      VB.NET-Quellcode

      1. ''' <summary>
      2. ''' Merkt sich die letzte Sortierrichtung, anfänglich unsortiert.
      3. ''' </summary>
      4. Private IDPersonDisplayMemberComboBoxColumnSortDirection As SortOrder = SortOrder.None
      5. Sub DoTheSort()
      6. If Me.TestDataSet.Material.Rows.Count > 0 Then ' Zur Vermeidung von NullReference-Fehlern.
      7. ' Deklarierung der Datenbank
      8. Dim dt As DataTable = Nothing
      9. ' Verwendung der gemerkten SortDirection, um daraus die neue Sortierreihenfolge abzuleiteen.
      10. ' Hier gewählt: Ascending, Descending, None.
      11. ' Kann natürlich beliebig angepasst werden.
      12. Select Case IDPersonDisplayMemberComboBoxColumnSortDirection
      13. Case SortOrder.None
      14. IDPersonDisplayMemberComboBoxColumnSortDirection = SortOrder.Ascending
      15. dt = Me.TestDataSet.Material.OrderBy(Function(p) p.PersonRow.Name).CopyToDataTable
      16. Case SortOrder.Ascending
      17. IDPersonDisplayMemberComboBoxColumnSortDirection = SortOrder.Descending
      18. dt = Me.TestDataSet.Material.OrderByDescending(Function(p) p.PersonRow.Name).CopyToDataTable
      19. Case SortOrder.Descending
      20. IDPersonDisplayMemberComboBoxColumnSortDirection = SortOrder.None
      21. dt = Me.TestDataSet.Material.OrderByDescending(Function(p) p.ID).CopyToDataTable
      22. End Select
      23. Me.TestDataSet.Material.Clear()
      24. Me.TestDataSet.Material.Merge(dt)
      25. Me.IDPersonDisplayMemberComboBoxColumn.HeaderCell.SortGlyphDirection = IDPersonDisplayMemberComboBoxColumnSortDirection
      26. End If
      27. End Sub
      • Die neue Sortiereihenfolge wird festgelegt.
      • Die zu sortierende Datentabelle wird mit LINQ in die gewünschte Reihenfolge gebracht.
      • Das Funktionsergebnis wird als Datatable dargestellt.
      • Die Daten der Original-Datatable werden gelöscht.
      • Die oben us der LINQ-Abfrage neu erstellte Datenbank wird mit der Original-datenbank "gemerged"
      • Das Zeichen für die Sortierreihenfolge wird in der DatagridViewColumn.Headercell entsprechend der neuen Sortierreihenfolge gesetzt.
      Das war's schon.

      Eins sollte noch bedacht werden:
      Das Datatable.Clear löscht natürlich alle bis dahin erfolgten Veränderungen an der Datatable. Mir fällt nix ein, wie das über den Merge-Prozess gerettet werden kann.
      Da sollte man sich Lösungen überlegen, die dem jeweiligen Projekt angemessen sind.

      Ich füge ein Beispielprojekt bei, das diese Funktionalität darstellt. Auf der MainForm sind 3 Datagridviews:
      Ganz links die Personen, in der Mitte die klassische Sortier-Funktionalität und rechts die Sortierung nach dem Displayitem:

      Dateien