DataGridView speichern

  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von f0x.

    DataGridView speichern

    Hallo,

    ich will den Zustand eines DataGridView möglichst vollständig speichern und wieder laden können. Inklusive Checkbox- und Image-Spalten. Ist hier der ComplexConverter das einfachste Mittel der Wahl?

    Aber wie muß ich die Reihen / Einträge konvertieren? Und wie kann ich das DGV hinterher wiederherstellen?

    VB.NET-Quellcode

    1. Private Sub _Memory_Convert(ByVal sender As Object, ByVal e As ComplexConverter.EventArg) Handles _Memory.Convert
    2. ' DataGridView-Spaltenbreiten konvertieren
    3. For Each Col As ColumnHeader In DataGridView1.Columns
    4. e.ConvertValue(Col.Width)
    5. Next
    6. 'DataGridView-Items konvertieren
    7. '...
    8. End Sub


    Beispiel-Generierung eines DGV

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. With DataGridView1
    3. .Columns.Clear()
    4. ' 2 Spalten TextBoxColumn
    5. .Columns.Add("Spalte1", "Jahreszeit")
    6. .Columns.Add("Spalte2", "Temperatur")
    7. ' Spalte CheckBoxColumn
    8. Dim ChkBxCol As New DataGridViewCheckBoxColumn
    9. ChkBxCol.HeaderText = "Warme Kleidung"
    10. .Columns.Add(ChkBxCol)
    11. ' Spalte ImageColumn
    12. Dim ImgCol As New DataGridViewImageColumn
    13. ImgCol.HeaderText = "Bilder"
    14. .Columns.Add(ImgCol)
    15. ' Spalte LinkColumn
    16. Dim LnkCol As New DataGridViewLinkColumn
    17. LnkCol.HeaderText = "Link"
    18. .Columns.Add(LnkCol)
    19. ' Spalte ComboBoxColumn mit Einträgen
    20. Dim ComboCol As New DataGridViewComboBoxColumn
    21. DataGridView1.Columns.Add(ComboCol)
    22. With ComboCol
    23. .HeaderText = "Combo"
    24. .Items.Add("Beachball")
    25. .Items.Add("Strandkorb")
    26. .Items.Add("Ski")
    27. .Items.Add("Schlitten")
    28. End With
    29. ' Zeilen füllen (jede Zeile in einem Rutsch)
    30. .Rows.Add("Sommer", "Warm", False, Me.Icon, "test1",
    31. "Beachball")
    32. .Rows.Add("Winter", "Kalt", True, Me.Icon, "test2",
    33. "Ski")
    34. End With
    35. End Sub


    Damit schreibe und lade ich die Einstellungen

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button4.Click
    2. Using outputFile As New StreamWriter("C:\Users\axb\Desktop\LB.txt")
    3. outputFile.Write(_Memory.CreateDataString())
    4. End Using
    5. End Sub
    6. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button5.Click
    7. Using inputFile As New StreamReader("C:\Users\axb\Desktop\LB.txt")
    8. TextBox1.Text = inputFile.ReadToEnd()
    9. End Using
    10. End Sub


    Ausgelagert aus ComplexConverter: alles in einen String und zurück . ~Thunderbolt

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

    @f0x Willkommen im Forum. :thumbup:
    Daten im DataGridView sollten nicht gespeichert werden, sondern die einer DataTable, die Du dem DGV als DataSource anhängst.
    Diese DataTable kannst Du per WriteXml(...) und LoadXml(...) handeln. Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich schließe mich der frage an:

    wie kann ich, vorrausgesetzt es ist im dgv erlaubt, beispielsweise die anordnung der spalten speichern?

    der user kann bei mir die reihenfolge selbst sortieren, da wäre es nett wenn diese beim erneuten start festgehalten wird, außerdem wäre es nett, wenn spalten auch "ausgeblendet" werden könnten (ähnlich wie bei excel)
    Gruß Hannes
    @hans im glück
    Aus- und einblenden geht so:

    VB.NET-Quellcode

    1. Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
    2. Me.DataGridView1.Columns(1).Visible = CheckBox1.Checked
    3. End Sub
    Tauschen geht so:

    VB.NET-Quellcode

    1. Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
    2. If CheckBox2.Checked Then
    3. table.Columns("Coordinate").SetOrdinal(0)
    4. table.Columns("Value").SetOrdinal(1)
    5. Else
    6. table.Columns("Coordinate").SetOrdinal(1)
    7. table.Columns("Value").SetOrdinal(0)
    8. End If
    9. Me.DataGridView1.DataSource = Nothing
    10. Me.DataGridView1.DataSource = Me.table
    11. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    danke !

    das bedeutet: ich ändere nicht die reihenfolge im grid, sondern die reihenfolge der spalten in der tabelle! und durch das databinding passt sich das grid automatisch an.

    bequem wäre also für die gui bspw ein contextmenu mit eintrag pro column, dann kann der user über rechtsklick ein und ausschalten.

    und beim speichern lese ich die aktuelle position mit System.Data.DataColumn.Ordinal aus? (ausm Obj Explorer ausgegraben)
    der user kann ja die spalten per mouse d&d verschieben, dann muss ich ja beim schließen abfragen wo sich die spalten derzeit befinden oder?
    Gruß Hannes

    hans im glück schrieb:

    beim schließen
    vielleicht nicht, sondern gleich beim Umsortieren, da ist die Info parat.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich meinte die Rheinfolge der Spalten.
    Also wenn der User zum Beispiel die letzte Spalte an Position 2 zieht und die 2. Spalte an Position 4 usw., wie/wo speichere ich dann diesen Zustand ab, sodass beim erneuten Start des Programms, der User wieder SEINE Ansicht der Spalten hat.
    "Hier könnte Ihre Werbung stehen..."
    Ich denke, das ist eine List(Of Strings), die kannst Du in My.Settings als StringCollection speichern.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die Sort-Property, und auch die DgvColumn.DisplayIndex-Property - das sind Sachen, die kann man mit ComplexConverter gut abhandeln.

    Also man kann damit Daten speichern und restaurieren, sehr vielfältig.

    Aber Controls nicht, weil Controls kann man garnicht abspeichern.
    Das ist ja eines der Probleme, wenn man Daten und Oberfläche nicht trennt.
    Bzw. wenn man Controls dynamisch generiert.

    Ein Control (oder auch eine DGVColumn) hält zig Referenz-Verweise auf andere Objekte, und ohne diese Verweise wäre es nicht arbeitsfähig, ja nichtmal denkbar.
    Und die ganzen Referenzen kann man ja nicht mit-abspeichern, da hätte man am Ende das ganze Betriebssystem auf Platte.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo,

    ich hab viel rumgetüftelt, bin aber mit der StringCollection nicht weiter gekommen.
    Habe dann einen StringBuilder genommen beim schreiben und beim Lesen den String wieder gesplitet.
    Funktioniert soweit (ich habe mal versucht es in Kommentaren zu erklären):

    VB.NET-Quellcode

    1. 'Funktion um den Index und DisplayIndex aller Spalten des DGV zu speichern
    2. Private Function dgvWriteColOrder(ByVal dgv As DataGridView) As String
    3. Dim strColOrder As New StringBuilder() 'neuen StringBuilder erstellen um den Index und DisplayIndex zu speichern
    4. For i As Integer = 0 To dgv.Columns.Count - 1 'alle Spalten des DGV durchgehen
    5. If strColOrder.Length > 0 Then strColOrder.Append(";") 'sofern schon Einträge vorhanden sind, sollen diese mit ; getrennt werden
    6. strColOrder.Append(dgv.Columns(i).Index & "," & dgv.Columns(i).DisplayIndex) 'den Index und den DisplayIndex jeder Spalte getrennt mit , in den Strinbuilder schreiben
    7. Next
    8. Return strColOrder.ToString 'komplette Liste zurück geben
    9. End Function
    10. 'Sub um die gespeicherten Index und DisplayIndex wieder dem DGV zuzuordnen
    11. Sub dgvReadColOrder(ByVal dgv As DataGridView, ByVal colOrder As String)
    12. If colOrder.Length > 0 Then 'wenn im übergebenen String etwas drinn steht, dann Spliten
    13. Dim strCols() As String = Split(colOrder, ";") 'String Array Splitten nach ;
    14. For i As Integer = 0 To strCols.Length - 1 'alle gesplitteten Einträge durchgehen
    15. Dim colIndex As Integer = CInt(strCols(i).Split(CChar(","))(0)) 'und der Variablen für den Spalten Index zuweisen, erste Array Dimension = Index, 2. Dimension = DisplayIndex
    16. Dim colDisplayIndex As Integer = CInt(strCols(i).Split(CChar(","))(1)) 'sowie den 2. Eintrag der DisplayIndex Variablen zuweisen
    17. dgv.Columns(colIndex).DisplayIndex = colDisplayIndex 'Jeder Spalte die entsprechenden Werte zuweisen
    18. Next
    19. End If
    20. End Sub


    Aufruf beim Schließen der Form:

    VB.NET-Quellcode

    1. Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    2. My.Settings.dgvColOrder = dgvWriteColOrder(dgvTest) 'funktion aufrufen und Spaltenanordnung des angegebenen DGV speichern
    3. End Sub


    Aufruf beim Laden der Form:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    2. dgvReadColOrder(dgvTest, My.Settings.dgvColOrder) 'Sub aufrufen um die Spalten des angegebenen DGV mit der Settingsliste anordnen
    3. End Sub
    "Hier könnte Ihre Werbung stehen..."
    2 Dinge auf schnelle:
    1. Schmeiss den Generalimport auf Microsoft.VisualBasic raus - dann vermeidest du die zB vb6-Split-Methode und lernst die wirklichen Möglichkeiten der String-Klasse kennen.
      Visual Studio - Empfohlene Einstellungen
    2. einen Char notiert man in vb.net nicht mit CChar(","), sondern so: ","c




    Danke @ErfinderDesRades. Bin mit meinem VS umgezogen auf ein Surface und hab einige Einstellungen verloren.
    Jetzt weis ich wieder was ich vergessen hatte :D

    EDIT: So, nachdem der Deppenspace raus ist hab ich die Sub nochmal angepasst:

    VB.NET-Quellcode

    1. 'Sub um die gespeicherten Index und DisplayIndex wieder dem DGV zuzuordnen
    2. Sub dgvReadColOrder(ByVal dgv As DataGridView, ByVal colOrder As String)
    3. If colOrder.Length > 0 Then 'wenn im übergebenen String etwas drinn steht, dann Spliten
    4. Dim strCols() As String = colOrder.Split(";"c) 'String Array Splitten nach ;
    5. For i As Integer = 0 To strCols.Length - 1 'alle gesplitteten Einträge durchgehen
    6. Dim colIndex As Integer = CInt(strCols(i).Split(","c)(0)) 'und der Variablen für den Spalten Index zuweisen
    7. Dim colDisplayIndex As Integer = CInt(strCols(i).Split(","c)(1)) 'sowie den 2. Eintrag der DisplayIndex Variablen zuweisen
    8. dgv.Columns(colIndex).DisplayIndex = colDisplayIndex 'Jeder Spalte die entsprechenden Werte zuweisen
    9. Next
    10. End If
    11. End Sub

    "Hier könnte Ihre Werbung stehen..."

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

    Ich hab noch bischen rumgebastelt am CC, und Update gemacht. Hier die Dgv-Persistenz, wie ich sie im Tut nu auch drinne hab:

    VB.NET-Quellcode

    1. Private Sub _Memory_Convert(sender As Object, e As ComplexConverter.EventArg) Handles _Memory.Convert
    2. e.ConvertValue(Me.Bounds)
    3. For Each col As DataGridViewColumn In Dgv.Columns
    4. e.ConvertValue(col.HeaderText)
    5. e.ConvertValue(col.DisplayIndex)
    6. e.ConvertValue(col.Width)
    7. Next
    8. e.ConvertValue(Dgv.RowCount)
    9. For Each rw As DataGridViewRow In Dgv.Rows
    10. e.ConvertValue(rw.Height)
    11. Next
    12. For x = 0 To Dgv.ColumnCount - 1
    13. For y = 0 To Dgv.RowCount - 2
    14. e.ConvertExplicitTyped(Of String)(Dgv(x, y).Value)
    15. Next
    16. Next
    17. End Sub
    Das speichert Spalten, Zeilen, Zellwerte, Form-Abmasse. Spalten sind anordnebar, Zeilen+Spalten größenverstellbar.
    Das mit dem RowCount (#8) geht übrigens nur bei ungebundenem Dgv, also wenn man Dgv richtig benutzt, dann hat man für die Zell-Werte ja eh eine andere Persistenz. (Auch bräuchte man die ColumnHeaders nicht zu speichern.)

    Warum speicherst du auch die ColIndizees? Das kriegt der User doch garnet zu sehen - für den User ist doch nur der DisplayIndex relevant?
    ich dachte eigentlich, das ich die Columns anhand des Indexes identifiziere und dann der identifizierten Column einen neuen DisplayIndex zuweise...

    EDIT: P.S. ich muss mir glaub mal deine ComplexConverter Geschichte angucken...
    "Hier könnte Ihre Werbung stehen..."