CheckedListView anzeige Column.Headertext, aber Column.Name auslesen

  • VB.NET
  • .NET (FX) 4.0

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    CheckedListView anzeige Column.Headertext, aber Column.Name auslesen

    Hallo zusammen.

    Ich lasse mir für einen Excel-Export eine CheckedListView basteln, worin die ColumnHeaders zur Auswahl angezeigt werden.
    Die Headers sind ja "lesefreundlich" und können durchaus (je nach Anwendungsfall) auch mal mehrfach vorkommen. Dann gibt's
    beim Export natürlich Müll...

    Also wollte ich nun gerne, dass nach wie vor der Headertext in der CheckedListbox erscheint, jedoch die DataGridViewColumn ansich ausgelesen wird.
    Leider gibt's keinen "versteckten Namen", den ich der Listbox mitgeben kann.

    Hat jemand eine Idee?
    Aktuell mache ich das so (für den Headertext):

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary> Stellt einen Dialog zur Auswahl des Inhalts eins DGV zum Export oder Kopieren bereit. </summary>
    2. <Extension>
    3. Public Sub copyExportSelection(dgv As DataGridView, excel As Boolean, Optional orderBy As String = Nothing)
    4. Using dlg As New dlgDGVcopyExport
    5. Dim listbox = dlg.chkLbSpalten
    6. For Each col As DataGridViewColumn In dgv.Columns
    7. If col.Visible Then
    8. listbox.Items.Add(col.HeaderText)
    9. End If
    10. Next
    11. For i = 0 To listbox.Items.Count - 1
    12. listbox.SetItemChecked(i, True) 'alle Items auf Checked setzen
    13. Next
    14. If dlg.ShowDialog <> DialogResult.OK Then Return
    15. Dim lstCol As New List(Of String)
    16. For Each chkItm In listbox.CheckedItems
    17. lstCol.Add(chkItm.ToString)
    18. Next
    19. Select Case True
    20. Case dlg._Selection = "all"
    21. If excel Then
    22. exportSelectionToExcel(dgv, "Export", lstCol, dlg._header)
    23. Else
    24. copySelectionToClipboard(dgv, lstCol, dlg._header)
    25. End If
    26. Case dlg._Selection = "marked"
    27. Dim lstRow = (From rw In dgv.SelectedRows.Cast(Of DataGridViewRow)() Order By rw.Index).ToList
    28. If excel Then
    29. exportSelectionToExcel(dgv, "Export", lstCol, dlg._header, lstRow)
    30. Else
    31. copySelectionToClipboard(dgv, lstCol, dlg._header, lstRow)
    32. End If
    33. End Select
    34. End Using
    35. End Sub

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tragl“ ()

    tragl schrieb:

    Also wollte ich nun gerne, dass nach wie vor der Headertext in der CheckedListbox erscheint, jedoch die DataGridViewColumn ansich ausgelesen wird.
    Klarer Fall für Databinding.
    Bastel eine kleine Klasse mit zwei Properties.
    Füll eine List(Of ) damit ab, binde per Code die chkListbox dran, unter Angabe von DisplayMember.
    Ich glaub mit den CheckedItems kriegste dann deine Objekte wieder.
    (Probiert habichs nicht - ich mach sowas lieber mit dgv)
    @ErfinderDesRades
    Danke für den Hinweis, find ich sehr umständlich - dachte das ging einfacher.
    Hab's an anderer Stelle nun probiert und klappt:

    VB.NET-Quellcode

    1. Private Class dgvCols
    2. Private colName As String
    3. Private colHeadertext As String
    4. Property name As String
    5. Get
    6. Return colName
    7. End Get
    8. Set(value As String)
    9. colName = value
    10. End Set
    11. End Property
    12. Property headertext As String
    13. Get
    14. Return colHeadertext
    15. End Get
    16. Set(value As String)
    17. colHeadertext = value
    18. End Set
    19. End Property
    20. End Class


    VB.NET-Quellcode

    1. ''' <summary> Stellt dem User ein DLG zur Verfügung, worin er auswählen kann welche DGV-Columns ihm angezeigt werden sollen.
    2. ''' Diese Auswahl wird in der Datenbank persistiert und beim nächsten Öffnen abgerufen </summary>
    3. Private Sub setCols(dgv As DataGridView, rwAppSettings As AppSettingsRow)
    4. Using dlg As New dlgChkLb
    5. Dim lb = dlg.chkLb
    6. Dim lstCol As New List(Of dgvCols)
    7. Dim selectedColNames As New List(Of String)
    8. Dim lstAdminCols = getDefaultAdminCols(dgv)
    9. For Each col As DataGridViewColumn In dgv.Columns
    10. If _uAdmin Then
    11. lstCol.Add(New dgvCols With {.name = col.Name, .headertext = col.HeaderText})
    12. Else
    13. If Not lstAdminCols.Any(Function(x) x.Equals(col.Name)) Then lstCol.Add(New dgvCols With {.name = col.Name, .headertext = col.HeaderText})
    14. End If
    15. Next
    16. lb.DataSource = lstCol
    17. lb.DisplayMember = "headertext"
    18. lb.ValueMember = "name"
    19. If Not rwAppSettings.strSetting = "" Then
    20. For Each colName In getColList(rwAppSettings)
    21. For i = 0 To lb.Items.Count - 1
    22. Dim itm = DirectCast(lb.Items(i), dgvCols)
    23. If itm.name = colName Then
    24. lb.SetItemChecked(i, True)
    25. End If
    26. Next
    27. Next
    28. End If
    29. If dlg.ShowDialog <> DialogResult.OK Then Return
    30. For Each itm In lb.CheckedItems
    31. selectedColNames.Add($"{DirectCast(itm, dgvCols).name}")
    32. Next
    33. rwAppSettings.strSetting = buildColString(selectedColNames)
    34. dgv.showSelectedCols(selectedColNames)
    35. End Using
    36. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Ich find das nicht soo übertrieben. Natürlich kann man vieles eleganter formulieren, aber viel zu tun macht eben viel Code.
    Eine starke Vereinfachung aber:

    VB.NET-Quellcode

    1. Private Class dgvCols
    2. Property name As String
    3. Property headertext As String
    4. End Class
    Dieses Sprach-Feature heisst "AutoProperty".
    (Ich würd die Klasse übrigens singular benamen - ein Objekt davon stellt ja nur eine Dgv-Column dar /Klugsch...)
    Die längere Methode habich jetzt auch bisserl eingedampft:

    VB.NET-Quellcode

    1. ''' <summary> Stellt dem User ein DLG zur Verfügung, worin er auswählen kann welche DGV-Columns ihm angezeigt werden sollen.
    2. ''' Diese Auswahl wird in der Datenbank persistiert und beim nächsten Öffnen abgerufen </summary>
    3. Private Sub setCols(dgv As DataGridView, rwAppSettings As AppSettingsRow)
    4. Using dlg As New dlgChkLb
    5. Dim lb = dlg.chkLb
    6. Dim lstCol As New List(Of dgvCols)
    7. Dim selectedColNames As New List(Of String)
    8. Dim lstAdminCols = getDefaultAdminCols(dgv)
    9. For Each col As DataGridViewColumn In dgv.Columns
    10. If Not _uAdmin AndAlso lstAdminCols.Contains(col.Name) Then Continue For
    11. lstCol.Add(New dgvCols With {.Name = col.Name, .headertext = col.HeaderText})
    12. Next
    13. lb.DataSource = lstCol
    14. lb.DisplayMember = "headertext"
    15. lb.ValueMember = "name"
    16. For Each colName In getColList(rwAppSettings)
    17. For i = 0 To lb.Items.Count - 1
    18. If DirectCast(lb.Items(i), dgvCols).name = colName Then lb.SetItemChecked(i, true)
    19. Next
    20. Next
    21. If dlg.ShowDialog <> DialogResult.OK Then Return
    22. For Each itm In lb.CheckedItems
    23. selectedColNames.Add($"{DirectCast(itm, dgvCols).name}")
    24. Next
    25. rwAppSettings.strSetting = buildColString(selectedColNames)
    26. dgv.showSelectedCols(selectedColNames)
    27. End Using
    28. End Sub
    Eine erforderliche Anpassung dafür ist, getColList(rwAppSettings) so zu gestalten, dass es statt auf einen Fehler zu laufen einfach eine Leere Liste returnt, wenn rwAppSettings leer ist.
    @ErfinderDesRades
    Ja sieht sehr gut aus. Du hast mir mit Contains auch wieder unbewusst einen Hinweis gegeben, dass ich mir
    .Any(Function(x)x. bla bla) sparen kann - Contains ist hier wesentlich kürzer :)

    Ich hab die Methode aber nochmal komplett geändert, weil ich mit eingebaut hab, dass auch die Col-Widths mit persistiert und
    beim Aufruf der Form mit restored werden.

    Allerdings hab ich da grad das Problem, dass die Cols trotzdem in Standardbreite angezeigt werden (DGV steht auf dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None)
    Also Form öffnen, verändern einer Breite eines Cols und Form schließen -> Wert wird korrekt gespeichert.
    Form erneut öffnen, Col hat wieder ihre Standardbreite -> Wert wurde mit dem Standardwert überschrieben ?(

    Ich geh davon aus, dass da beim Öffnen der Form der Wert über irgendein Event überschrieben wird.
    Hast du eine Idee, welches Event mir da einen Strich durch die Rechnung macht?

    Hier mal der komplette Kauderwelsch:

    Beim öffnen der Form in Form_Load wird folgendes aufgerufen: dgv.GetSetDgvColumnSettings(False, Me) <- ruft die vom User gewünschten sichtbaren Spalten auf und soll hier
    natürlich auch die Widths wiederherstellen -> tut er aktuell nicht

    Ändert man die Spalten-Anzeige (über Kontextmenu): dgv.GetSetDgvColumnSettings(True, Me)

    Beim schließen der Form: dgv.GetSetDgvColumnSettings(False, Me) <- hier werden dann u.A. auch die Col-Widths gespeichert

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary> prüft, ob eine Einstellung zur Anzeige der DGV-Columns vorhanden ist. Falls nicht, wird ein Default-Eintrag mit allen Columns erstellt. Außerdem kann
    2. ''' ist useHeaderText True, wird Column.Headertext anstelle Column.Name genutzt
    3. ''' ist setCol True, wird dem User ein DLG zur Auswahl der sichtbaren Columns angezeigt </summary>
    4. <Extension>
    5. Public Sub GetSetDgvColumnSettings(dgv As DataGridView, setCol As Boolean, frm As Form, Optional additionalInfo As String = Nothing)
    6. Dim settingName = $"dgvColSettings_{dgv.Name}_{frm.Name}_{_user}"
    7. Dim settingNameOriginCols = $"dgvColSettingsOrigin_{dgv.Name}_{frm.Name}_{_user}"
    8. If additionalInfo IsNot Nothing Then
    9. settingName = $"dgvColSettings_{dgv.Name}_{frm.Name}_{additionalInfo}_{_user}"
    10. settingNameOriginCols = $"dgvColSettingsOrigin_{dgv.Name}_{frm.Name}_{additionalInfo}_{_user}"
    11. End If
    12. Dim rwAppSettingsOriginCols = getAppSettingsRow(settingNameOriginCols)
    13. If rwAppSettingsOriginCols Is Nothing Then rwAppSettingsOriginCols = Dts.AppSettings.AddAppSettingsRow(getUserRow, settingNameOriginCols, buildColString(getActualDgvCols(dgv)), 0, 0, 0, _defaultDate)
    14. Dim rwAppSettings = getAppSettingsRow(settingName)
    15. If rwAppSettings Is Nothing Then
    16. rwAppSettings = Dts.AppSettings.AddAppSettingsRow(getUserRow, settingName, buildColString(getActualDgvCols(dgv)), 0, 0, 0, _defaultDate)
    17. dgv.setSelectedCols(getColList(rwAppSettings))
    18. Else
    19. compare(dgv, rwAppSettingsOriginCols, rwAppSettings)
    20. If setCol Then
    21. ShowColSelectionDlg(dgv, rwAppSettings)
    22. Else
    23. dgv.setSelectedCols(getColList(rwAppSettings))
    24. End If
    25. End If
    26. Dts.SaveDtsWithoutBusyDlg()
    27. End Sub
    28. ''' <summary> Vergleicht gespeicherte Settings mit aktuellen Daten eines DGV und berücksichtigt
    29. ''' dabei die vom User gewählten sichtbaren Columns. Nicht mehr vorhandene Columns werden entfernt, neu hinzugefügte
    30. ''' werden dem User automatisch angezeigt. Col-Widths werden abgeglichen und bei Änderung mit geupdatet. </summary>
    31. Private Sub compare(dgv As DataGridView, rwSavedOrigin As AppSettingsRow, rwSetting As AppSettingsRow)
    32. '.LeftCut(";"c) = col.Name
    33. '.RightCut(";"c).LeftCut(";"c) = col.Width
    34. '.RightCut(";"c).RightCut(","c) = col.Visible
    35. Dim actualOriginCols = getActualDgvCols(dgv) 'aktuelle Original-Auflistung
    36. Dim savedOriginCols = rwSavedOrigin.strSetting.Split("#"c).ToList 'gespeicherte Original-Auflistung
    37. Dim savedVisibleCols = rwSetting.strSetting.Split("#"c).ToList 'gespeicherte Benutzerdefinierte Auflistung
    38. Dim neu = actualOriginCols.Where(Function(x) Not savedOriginCols.Any(Function(y) y.LeftCut(";"c).Equals(x.name))).ToList 'neu hinzugefügte Cols
    39. Dim entfernt = savedOriginCols.Where(Function(x) Not actualOriginCols.Any(Function(y) y.name.Equals(x.LeftCut(";"c)))).ToList 'entfernte Cols
    40. For Each col In neu
    41. savedVisibleCols.Add($"{col.name};{col.width},{col.visible}") 'neue Cols hinzufügen
    42. Next
    43. entfernt.ForEach(AddressOf savedVisibleCols.Remove) 'entfernte Cols rausschmeißen
    44. rwSavedOrigin.strSetting = buildColString(actualOriginCols) 'neuen Origin-String bauen
    45. Dim savedNew As New List(Of dgvCol)
    46. For Each str In savedVisibleCols 'neue aktualisierte Col-Liste
    47. Dim itm As New dgvCol
    48. Dim actual = actualOriginCols.First(Function(x) x.name = str.LeftCut(";"c))
    49. If actual.width <> CInt(str.RightCut(";"c).LeftCut(","c)) Then
    50. itm = New dgvCol With {.name = str.LeftCut(";"c), .width = actual.width, .visible = CBool(str.RightCut(";"c).RightCut(","c))} 'neue Width benutzen
    51. Else
    52. itm = New dgvCol With {.name = str.LeftCut(";"c), .width = CInt(str.RightCut(";"c).LeftCut(","c)), .visible = CBool(str.RightCut(";"c).RightCut(","c))} 'alte Width benutzen
    53. End If
    54. savedNew.Add(itm)
    55. Next
    56. rwSetting.strSetting = buildColString(savedNew)
    57. End Sub
    58. ''' <summary> Returned die aktuell enthaltenen Columns des DGV </summary>
    59. Private Function getActualDgvCols(dgv As DataGridView) As List(Of dgvCol)
    60. Dim lst As New List(Of dgvCol)
    61. Dim lstAdminCols = getDefaultAdminCols(dgv)
    62. For Each col As DataGridViewColumn In dgv.Columns
    63. Dim itm As New dgvCol With {.name = col.Name, .headertext = col.HeaderText, .width = col.Width, .visible = col.Visible}
    64. If _uAdmin Then
    65. lst.Add(itm)
    66. Else
    67. If Not lstAdminCols.Contains(col.Name) Then lst.Add(itm)
    68. End If
    69. Next
    70. Return lst
    71. End Function
    72. ''' <summary> Stellt dem User ein DLG zur Verfügung, worin er auswählen kann welche DGV-Columns ihm angezeigt werden sollen. </summary>
    73. Private Sub ShowColSelectionDlg(dgv As DataGridView, rwAppSettings As AppSettingsRow)
    74. Using dlg As New dlgChkLb
    75. Dim lb = dlg.chkLb
    76. Dim lstCol As New List(Of dgvCol)
    77. Dim selectedColNames As New List(Of dgvCol)
    78. Dim lstAdminCols = getDefaultAdminCols(dgv)
    79. For Each col As DataGridViewColumn In dgv.Columns
    80. If Not _uAdmin AndAlso lstAdminCols.Contains(col.Name) Then Continue For
    81. lstCol.Add(New dgvCol With {.name = col.Name, .headertext = col.HeaderText, .width = col.Width})
    82. Next
    83. lb.DataSource = lstCol
    84. lb.DisplayMember = "headertext"
    85. lb.ValueMember = "name"
    86. For Each colName In getColList(rwAppSettings)
    87. For i = 0 To lb.Items.Count - 1
    88. If DirectCast(lb.Items(i), dgvCol).name = colName.LeftCut(";"c) Then
    89. If colName.RightCut(";"c).RightCut(",") = "True" Then lb.SetItemChecked(i, True) 'gespeicherte Visible auch in der Listbox anhaken
    90. End If
    91. Next
    92. Next
    93. If dlg.ShowDialog <> DialogResult.OK Then Return
    94. For Each itm In lb.CheckedItems
    95. selectedColNames.Add(DirectCast(itm, dgvCol))
    96. Next
    97. Dim savedNew As New List(Of dgvCol)
    98. For Each str In rwAppSettings.strSetting.Split("#"c).ToList
    99. Dim selected = selectedColNames.FirstOrDefault(Function(x) x.name = str.LeftCut(";"c))
    100. If selected IsNot Nothing Then 'wurde ausgewählt
    101. selected.visible = True
    102. savedNew.Add(selected)
    103. Else 'wurde nicht ausgewählt -> visible auf False setzen, Rest beibehalten
    104. Dim itm As New dgvCol With {.name = str.LeftCut(";"c), .width = CInt(str.RightCut(";"c).LeftCut(","c)), .visible = False}
    105. savedNew.Add(itm)
    106. End If
    107. Next
    108. rwAppSettings.strSetting = buildColString(savedNew) 'neuen String speichern
    109. dgv.setSelectedCols(getColList(rwAppSettings)) 'Änderungen anzeigen
    110. End Using
    111. End Sub
    112. ''' <summary> Returned eine Liste aus dem strSetting-String </summary>
    113. Private Function getColList(rwAppSettings As AppSettingsRow) As List(Of String)
    114. Return rwAppSettings.strSetting.Split("#"c).ToList
    115. End Function
    116. ''' <summary> erstellt einen String mit Separator "#" aus allen Cols in lstCol zum Persistieren in "strSetting" </summary>
    117. Private Function buildColString(lstCol As List(Of dgvCol)) As String
    118. Dim s = ""
    119. For Each col In lstCol
    120. If s = "" Then
    121. s = $"{col.name};{col.width},{col.visible}"
    122. Else
    123. s = $"{s}#{col.name};{col.width},{col.visible}"
    124. End If
    125. Next
    126. Return s
    127. End Function
    128. Private Class dgvCol
    129. Property name As String
    130. Property headertext As String
    131. Property width As Integer
    132. Property visible As Boolean
    133. End Class


    VB.NET-Quellcode

    1. ''' <summary> Return die Default-Admin Columns, nach Prüfung ob diese auch vorhanden sind </summary>
    2. <Extension>
    3. Public Function getDefaultAdminCols(dgv As DataGridView) As List(Of String)
    4. Dim lstAdminCol As New List(Of String) From {"ID", "IDDataGridViewTextBoxColumn",
    5. "logTimestamp", "logTimestamp2", "logTimestampDataGridViewTextBoxColumn", "LogTimestampDataGridViewTextBoxColumn",
    6. "logType", "logType2", "logTypeDataGridViewTextBoxColumn", "LogTypeDataGridViewTextBoxColumn",
    7. "logUser", "logUser2", "logUserDataGridViewTextBoxColumn", "LogUserDataGridViewTextBoxColumn"
    8. }
    9. Dim lstNew As New List(Of String)
    10. For Each colName In lstAdminCol
    11. If colExists(dgv, colName) Then lstNew.Add(colName)
    12. Next
    13. 'urspr. Liste durchlaufen und String rausschmeißen ging nicht (mit for each, fehler in aufzählung, mit i wurde das übersprungen!)
    14. Return lstNew
    15. End Function
    16. ''' <summary> Überprüft, ob eine Column anhand ColumnName exisitert </summary>
    17. Private Function colExists(dgv As DataGridView, colName As String) As Boolean
    18. For i = 0 To dgv.Columns.Count - 1
    19. If dgv.Columns(i).Name = colName Then Return True
    20. Next
    21. Return False
    22. End Function
    23. ''' <summary> zeigt bestimmte Columns aus lstCol an und blendet alle anderen aus, außerdem werden die Col-Widths wiederhergestellt </summary>
    24. <Extension>
    25. Public Sub setSelectedCols(dgv As DataGridView, lstColNames As List(Of String))
    26. For Each col As DataGridViewColumn In dgv.Columns
    27. Dim selected = lstColNames.First(Function(x) x.LeftCut(";"c) = col.Name)
    28. Dim visible = CBool(selected.RightCut(";"c).RightCut(","c))
    29. Dim width = CInt(selected.RightCut(";").LeftCut(","))
    30. col.Visible = visible
    31. col.Width = width
    32. Next
    33. End Sub




    EDIT: hat sich erledigt - ich hab' mal wieder was verdaddelt gehabt :rolleyes: hier nun der Funktionierende Kauderwelsch (vielleicht kann das ja jemand gebrauchen. anstatt das in's DataSet zu Persistieren, kann man natürlich auch die my.settings nutzen):
    aktualisierter Aufruf bei frm_Closing: dgv.GetSetDgvColumnSettings(False, Me,, True)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary> Return die Default-Admin Columns, nach Prüfung ob diese auch vorhanden sind </summary>
    2. <Extension>
    3. Public Function getDefaultAdminCols(dgv As DataGridView) As List(Of String)
    4. Dim lstAdminCol As New List(Of String) From {"ID", "IDDataGridViewTextBoxColumn",
    5. "logTimestamp", "logTimestamp2", "logTimestampDataGridViewTextBoxColumn", "LogTimestampDataGridViewTextBoxColumn",
    6. "logType", "logType2", "logTypeDataGridViewTextBoxColumn", "LogTypeDataGridViewTextBoxColumn",
    7. "logUser", "logUser2", "logUserDataGridViewTextBoxColumn", "LogUserDataGridViewTextBoxColumn"
    8. }
    9. Dim lstNew As New List(Of String)
    10. For Each colName In lstAdminCol
    11. If colExists(dgv, colName) Then lstNew.Add(colName)
    12. Next
    13. 'urspr. Liste durchlaufen und String rausschmeißen ging nicht (mit for each, fehler in aufzählung, mit i wurde das übersprungen!)
    14. Return lstNew
    15. End Function
    16. ''' <summary> Überprüft, ob eine Column anhand ColumnName exisitert </summary>
    17. Private Function colExists(dgv As DataGridView, colName As String) As Boolean
    18. For i = 0 To dgv.Columns.Count - 1
    19. If dgv.Columns(i).Name = colName Then Return True
    20. Next
    21. Return False
    22. End Function
    23. ''' <summary> zeigt bestimmte Columns aus lstCol an und blendet alle anderen aus, außerdem werden die Col-Widths wiederhergestellt </summary>
    24. <Extension>
    25. Public Sub setSelectedCols(dgv As DataGridView, lstColNames As List(Of String))
    26. For Each col As DataGridViewColumn In dgv.Columns
    27. Dim selected = lstColNames.FirstOrDefault(Function(x) x.LeftCut(";"c) = col.Name)
    28. If selected IsNot Nothing Then
    29. Dim visible = CBool(selected.RightCut(";"c).RightCut(","c))
    30. Dim width = CInt(selected.RightCut(";").LeftCut(","))
    31. col.Visible = visible
    32. col.Width = width
    33. Else
    34. col.Visible = False
    35. End If
    36. Next
    37. End Sub


    VB.NET-Quellcode

    1. ''' <summary> prüft, ob eine Einstellung zur Anzeige der DGV-Columns vorhanden ist. Falls nicht, wird ein Default-Eintrag mit allen Columns erstellt. Außerdem kann
    2. ''' ist useHeaderText True, wird Column.Headertext anstelle Column.Name genutzt
    3. ''' ist setCol True, wird dem User ein DLG zur Auswahl der sichtbaren Columns angezeigt </summary>
    4. <Extension>
    5. Public Sub GetSetDgvColumnSettings(dgv As DataGridView, setCol As Boolean, frm As Form, Optional additionalInfo As String = Nothing, Optional newColWidth As Boolean = False)
    6. If _userID = 0 Then Return
    7. Dim settingName = $"dgvColSettings_{dgv.Name}_{frm.Name}_{_user}"
    8. Dim settingNameOriginCols = $"dgvColSettingsOrigin_{dgv.Name}_{frm.Name}_{_user}"
    9. If additionalInfo IsNot Nothing Then
    10. settingName = $"dgvColSettings_{dgv.Name}_{frm.Name}_{additionalInfo}_{_user}"
    11. settingNameOriginCols = $"dgvColSettingsOrigin_{dgv.Name}_{frm.Name}_{additionalInfo}_{_user}"
    12. End If
    13. Dim rwAppSettingsOriginCols = getAppSettingsRow(settingNameOriginCols)
    14. If rwAppSettingsOriginCols Is Nothing Then rwAppSettingsOriginCols = Dts.AppSettings.AddAppSettingsRow(getUserRow, settingNameOriginCols, buildColString(getActualDgvCols(dgv)), 0, 0, 0, _defaultDate)
    15. Dim rwAppSettings = getAppSettingsRow(settingName)
    16. If rwAppSettings Is Nothing Then
    17. rwAppSettings = Dts.AppSettings.AddAppSettingsRow(getUserRow, settingName, buildColString(getActualDgvCols(dgv)), 0, 0, 0, _defaultDate)
    18. dgv.setSelectedCols(getColList(rwAppSettings))
    19. Else
    20. compare(dgv, rwAppSettingsOriginCols, rwAppSettings, newColWidth)
    21. If setCol Then
    22. ShowColSelectionDlg(dgv, rwAppSettings)
    23. Else
    24. dgv.setSelectedCols(getColList(rwAppSettings))
    25. End If
    26. End If
    27. Dts.SaveDtsWithoutBusyDlg()
    28. End Sub
    29. ''' <summary> Vergleicht gespeicherte Settings mit aktuellen Daten eines DGV und berücksichtigt
    30. ''' dabei die vom User gewählten sichtbaren Columns. Nicht mehr vorhandene Columns werden entfernt, neu hinzugefügte
    31. ''' werden dem User automatisch angezeigt. Col-Widths werden abgeglichen und bei Änderung mit geupdatet. </summary>
    32. Private Sub compare(dgv As DataGridView, rwSavedOrigin As AppSettingsRow, rwSetting As AppSettingsRow, newColWidth As Boolean)
    33. '.LeftCut(";"c) = col.Name
    34. '.RightCut(";"c).LeftCut(";"c) = col.Width
    35. '.RightCut(";"c).RightCut(","c) = col.Visible
    36. Dim actualOriginCols = getActualDgvCols(dgv) 'aktuelle Original-Auflistung
    37. Dim savedOriginCols = rwSavedOrigin.strSetting.Split("#"c).ToList 'gespeicherte Original-Auflistung
    38. Dim savedVisibleCols = rwSetting.strSetting.Split("#"c).ToList 'gespeicherte Benutzerdefinierte Auflistung
    39. Dim neu = actualOriginCols.Where(Function(x) Not savedOriginCols.Any(Function(y) y.LeftCut(";"c).Equals(x.name))).ToList 'neu hinzugefügte Cols
    40. Dim entfernt = savedOriginCols.Where(Function(x) Not actualOriginCols.Any(Function(y) y.name.Equals(x.LeftCut(";"c)))).ToList 'entfernte Cols
    41. For Each col In neu
    42. savedVisibleCols.Add($"{col.name};{col.width},{col.visible}") 'neue Cols hinzufügen
    43. Next
    44. entfernt.ForEach(AddressOf savedVisibleCols.Remove) 'entfernte Cols rausschmeißen
    45. rwSavedOrigin.strSetting = buildColString(actualOriginCols) 'neuen Origin-String bauen
    46. Dim savedNew As New List(Of dgvCol)
    47. For Each str In savedVisibleCols 'neue aktualisierte Col-Liste
    48. Dim itm As New dgvCol
    49. Dim actual = actualOriginCols.First(Function(x) x.name = str.LeftCut(";"c))
    50. If newColWidth Then
    51. itm = New dgvCol With {.name = str.LeftCut(";"c), .width = actual.width, .visible = CBool(str.RightCut(";"c).RightCut(","c))} 'neue Width benutzen
    52. Else
    53. itm = New dgvCol With {.name = str.LeftCut(";"c), .width = CInt(str.RightCut(";"c).LeftCut(","c)), .visible = CBool(str.RightCut(";"c).RightCut(","c))} 'alte Width benutzen
    54. End If
    55. savedNew.Add(itm)
    56. Next
    57. rwSetting.strSetting = buildColString(savedNew)
    58. End Sub
    59. ''' <summary> Returned die aktuell enthaltenen Columns des DGV </summary>
    60. Private Function getActualDgvCols(dgv As DataGridView) As List(Of dgvCol)
    61. Dim lst As New List(Of dgvCol)
    62. Dim lstAdminCols = getDefaultAdminCols(dgv)
    63. For Each col As DataGridViewColumn In dgv.Columns
    64. Dim itm As New dgvCol With {.name = col.Name, .headertext = col.HeaderText, .width = col.Width, .visible = col.Visible}
    65. If _uAdmin Then
    66. lst.Add(itm)
    67. Else
    68. If Not lstAdminCols.Contains(col.Name) Then lst.Add(itm)
    69. End If
    70. Next
    71. Return lst
    72. End Function
    73. ''' <summary> Stellt dem User ein DLG zur Verfügung, worin er auswählen kann welche DGV-Columns ihm angezeigt werden sollen. </summary>
    74. Private Sub ShowColSelectionDlg(dgv As DataGridView, rwAppSettings As AppSettingsRow)
    75. Using dlg As New dlgChkLb
    76. Dim lb = dlg.chkLb
    77. Dim lstCol As New List(Of dgvCol)
    78. Dim selectedColNames As New List(Of dgvCol)
    79. Dim lstAdminCols = getDefaultAdminCols(dgv)
    80. For Each col As DataGridViewColumn In dgv.Columns
    81. If Not _uAdmin AndAlso lstAdminCols.Contains(col.Name) Then Continue For
    82. lstCol.Add(New dgvCol With {.name = col.Name, .headertext = col.HeaderText, .width = col.Width})
    83. Next
    84. lb.DataSource = lstCol
    85. lb.DisplayMember = "headertext"
    86. lb.ValueMember = "name"
    87. For Each colName In getColList(rwAppSettings)
    88. For i = 0 To lb.Items.Count - 1
    89. If DirectCast(lb.Items(i), dgvCol).name = colName.LeftCut(";"c) Then
    90. If colName.RightCut(";"c).RightCut(",") = "True" Then lb.SetItemChecked(i, True) 'gespeicherte Visible auch in der Listbox anhaken
    91. End If
    92. Next
    93. Next
    94. If dlg.ShowDialog <> DialogResult.OK Then Return
    95. For Each itm In lb.CheckedItems
    96. selectedColNames.Add(DirectCast(itm, dgvCol))
    97. Next
    98. Dim savedNew As New List(Of dgvCol)
    99. For Each str In rwAppSettings.strSetting.Split("#"c).ToList
    100. Dim selected = selectedColNames.FirstOrDefault(Function(x) x.name = str.LeftCut(";"c))
    101. If selected IsNot Nothing Then 'wurde ausgewählt
    102. selected.visible = True
    103. savedNew.Add(selected)
    104. Else 'wurde nicht ausgewählt -> visible auf False setzen, Rest beibehalten
    105. Dim itm As New dgvCol With {.name = str.LeftCut(";"c), .width = CInt(str.RightCut(";"c).LeftCut(","c)), .visible = False}
    106. savedNew.Add(itm)
    107. End If
    108. Next
    109. rwAppSettings.strSetting = buildColString(savedNew) 'neuen String speichern
    110. dgv.setSelectedCols(getColList(rwAppSettings)) 'Änderungen anzeigen
    111. End Using
    112. End Sub
    113. ''' <summary> Returned eine Liste aus dem strSetting-String </summary>
    114. Private Function getColList(rwAppSettings As AppSettingsRow) As List(Of String)
    115. Return rwAppSettings.strSetting.Split("#"c).ToList
    116. End Function
    117. ''' <summary> erstellt einen String mit Separator "#" aus allen Cols in lstCol zum Persistieren in "strSetting" </summary>
    118. Private Function buildColString(lstCol As List(Of dgvCol)) As String
    119. Dim s = ""
    120. For Each col In lstCol
    121. If s = "" Then
    122. s = $"{col.name};{col.width},{col.visible}"
    123. Else
    124. s = $"{s}#{col.name};{col.width},{col.visible}"
    125. End If
    126. Next
    127. Return s
    128. End Function
    129. Private Class dgvCol
    130. Property name As String
    131. Property headertext As String
    132. Property width As Integer
    133. Property visible As Boolean
    134. End Class


    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „tragl“ ()