DGV Filtern Sortieren Besonderheiten

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    DGV Filtern Sortieren Besonderheiten

    Hallo,

    ich habe ein paar Fragen bezüglich DGV, da ich gerade daran bastel.

    Wenn man einen Spaltenkopf anklickt, löst das DGV automatisch eine Sortierung aus. Wie funktioniert diese Sortierung?
    Wenn ich die DataSource meiner BindingSource ändere, dann verschwindet diese Sortiermöglichkeit.
    Muss die DataSource dafür besonders geschaffen sein?

    Und kann man die Sortierung allgemein aufheben? Wenn ich zum Beispiel eine typisierte Tabelle als DataSource habe, dann wird die zumindest nicht selbst umsortiert, daher sollte das doch möglich sein.

    Und wo sitzt das Click-Event dafür eigentlich?

    Viele Grüße

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

    Haudruferzappeltnoch schrieb:

    Wie funktioniert diese Sortierung?
    Abhängig von DataSource oder vom blanken Inhalt. Wenn Du keine DataSource hast, versucht der Compiler das Beste draus zu machen. Packst Du ein Datum in eine Zelle und in der nächsten Zeile einen Text und versuchst zu sortieren, schmiert das Programm ab, weil das Programm dann nicht sortieren kann.

    Haudruferzappeltnoch schrieb:

    Und wo sitzt das Click-Event dafür eigentlich?
    Innerhalb der DGV-Klasse.
    Einfach mal das obige Szenario ausprobieren, dann siehst Du bei der Aufrufliste, welche DGV-internen Methoden dann aufgerufen werden:


    Wenn die DataSource keine Sortiermethode anbietet, die das DGV akzeptiert, wird einfach nicht sortiert.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Wie bietet eine DataSource eine Sortiermethode an?

    Ich hab das soweit für Anbindung an eine DataTable hingekriegt. Das Sortieren habe ich noch rausgefunden kann ich in den Columns über SortMode deaktivieren.
    Mit dem Headerclick habe ich mir stattdessen eine Filter Möglichkeit gebastelt. Außerdem habe ich eine Suchfunktion probiert. Ich würde einfach mal den Code posten, ich hab da glaub ich noch den ein oder anderen Schmu drin und eine Frage:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class Form1
    2. Friend Shared FilterValue As String = "" '''Behälter für FilterDialog Input
    3. Private dv As DataView '''für Ähnlichkeitssuche (DataSource ist die DataTable die in der BindingSource.DataMember Property angegeben ist, DataSource der BindingSource ist hingegen das DataSet
    4. Private Sub btnClearFilter_Click(sender As Object, e As EventArgs) Handles btnClearFilter.Click
    5. If Not BindingSource1.Filter.Contains("Gruppe") Then
    6. BindingSource1.Filter = String.Empty
    7. btnClearFilter.Visible = False
    8. lblClearFilter.Visible = False
    9. Else
    10. Dim idx = BindingSource1.Filter.IndexOf(" AND")
    11. BindingSource1.Filter = BindingSource1.Filter.Substring(0, idx)
    12. btnClearFilter.Visible = False
    13. lblClearFilter.Visible = False
    14. End If
    15. End Sub
    16. Private Sub cbHauptfilter_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles cbHauptfilter.SelectionChangeCommitted
    17. If cbHauptfilter.SelectedItem.ToString = "Alle" Then
    18. BindingSource1.Filter = String.Empty
    19. FilterValue = String.Empty
    20. If btnClearFilter.Visible Then btnClearFilter.Visible = False : lblClearFilter.Visible = False
    21. Else
    22. BindingSource1.Filter = $"Gruppe = '{cbHauptfilter.SelectedItem.ToString}'"
    23. End If
    24. End Sub
    25. Private Sub DGV1_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DGV1.ColumnHeaderMouseClick
    26. Dim idx = e.ColumnIndex
    27. Dim ColumnName = DGV1.Columns(idx).DataPropertyName
    28. If {"Artikel", "Ort"}.Contains(ColumnName) Then
    29. Using filter As New FilterDialog
    30. filter.Location = e.Location ''' Das hier geht nicht
    31. If filter.ShowDialog(Me) = DialogResult.OK Then
    32. If BindingSource1.Filter = String.Empty Then
    33. BindingSource1.Filter = $"{ColumnName} = {FilterValue}"
    34. ElseIf BindingSource1.Filter.Contains(ColumnName) Then
    35. Dim i = BindingSource1.Filter.IndexOf(ColumnName) + ColumnName.Length + 3
    36. BindingSource1.Filter = BindingSource1.Filter.Substring(0, i) & FilterValue
    37. Else
    38. BindingSource1.Filter &= $" AND {ColumnName} = {FilterValue}"
    39. End If
    40. If Not btnClearFilter.Visible Then
    41. btnClearFilter.Visible = True
    42. lblClearFilter.Visible = True
    43. End If
    44. End If
    45. End Using
    46. End If
    47. End Sub
    48. Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
    49. Dim LookUpString = tbSearch.Text
    50. Dim result = BindingSource1.Find("Kunde", LookUpString)
    51. If result = -1 Then
    52. dv.RowFilter = $"Kunde LIKE '*{LookUpString}*'"
    53. If dv.Count > 0 Then
    54. result = BindingSource1.Find("Kunde", dv(0)("Kunde"))
    55. End If
    56. End If
    57. If result = -1 Then MessageBox.Show("Keine Treffer") : Exit Sub
    58. DGV1.Rows(result).Selected = True
    59. DGV1.FirstDisplayedScrollingRowIndex = result
    60. End Sub
    61. End Class
    62. Friend Class FilterDialog
    63. Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
    64. Form1.FilterValue = tbFilterValue.Text
    65. End Sub
    66. End Class


    Die Suche mit der BindingSource.Find() berücksichtigt die die momentane Filterung? Das DataView ist ja unabhängig davon, das heißt so würde ich dann je nachdem ob vollständiger Match oder nur ähnlicher Match in unterschiedlichen Quellen suchen?

    Den FilterDialog, den ich aufrufe, würde ich auch gerne dort aufrufen, wo man geklickt hat. Aber e.Location, welches sich zwar so anhört als wäre es was ich brauche, gibt mir immer dieselben falschen Werte. FilterDialog.StartPosition habe ich auf Manual eingestellt.

    Haudruferzappeltnoch schrieb:

    Wie bietet eine DataSource eine Sortiermethode an?

    Sie implementiert das Interface IBindingList und/oder IBindingListView.
    Wenn du databinding-getrieben arbeitest, mit einem Dataset, ist das OnBord - nämlich vermittelst der Klassen BindingSource und DataView.
    Wobei BindingSource nur ein "Durchleiter" ist, die Umsetzung von Sortieren und Filtern geschieht im durch die BS gewrapperten DataView.
    Wenn die BS an ein Dataset gebunden ist.
    Ich hätte da noch etwas

    Es gibt ja einen DGV.SelectionMode, wenn der auf FullRowSelect steht, dann kann ich eine Zelle anklicken und bekomme in DGV.SelectedRows die Zeile die ich gewählt habe.
    Wenn der Mode hingegen auf RowHeaderSelect steht, dann bleibt DGV.SelectedRows leer.

    Ich würde gerne im Modus RowHeaderSelect eine Sammlung der Zeilen bekommen, die 1 oder mehr Zellen selected haben. Gibt es da einen ShortCut?

    Das ist was ich mache:

    VB.NET-Quellcode

    1. Dim selection = DGVGestelle.SelectedCells.Cast(Of DataGridViewCell)
    2. For Each cell In selection
    3. DGV.Rows(cell.RowIndex).Selected = True
    4. Next
    5. Dim selectedRows = DGV.SelectedRows.Cast(Of DataGridViewRow)

    Bei RowHeaderSelect wird eine Zeile dann vollständig markiert und in die SelectedRows aufgenommen, wenn - tja, das sagt ja der Modus schon - der RowHeader angeklickt wird. Dazu muss der natürlich sichtbar sein.
    Und um dann alle Zeilen und Zellen zu bekommen, die dann markiert sind:

    VB.NET-Quellcode

    1. Dim SelectedRows = DeinDGV.SelectedRows.Cast(Of DataGridViewRow)
    2. Dim SelectedCells = DeinDGV.SelectedRows.Cast(Of DataGridViewRow).SelectMany(Function(x) x.Cells.Cast(Of DataGridViewCell))

    Bilder
    • RowHeader.png

      4,75 kB, 195×244, 24 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Achso. Einen offiziellen Shortcut kenn ich nicht, kannst Du aber nachrüsten:

    VB.NET-Quellcode

    1. Private Sub DeinDGV_KeyDown(sender As Object, e As KeyEventArgs) Handles DeinDGV.KeyDown
    2. If e.Control AndAlso e.KeyValue = Keys.A Then
    3. DeinDGV.SelectedCells.Cast(Of DataGridViewCell).ToList.ForEach(Sub(x) DeinDGV.Rows(x.RowIndex).Selected = True)
    4. e.Handled = True
    5. End If
    6. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.