Problem mit DataGridView und XML Laden/Speichern

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

Es gibt 34 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Ja Natürlich hab ich das Beispiel gesehen und getestet.. Es wurden 100 Zeilen mit irgendwelchen Zahlen in ein xml Dokument geschrieben..
    Hab das geändert, also statt double string und int32 verwendet.. Jetzt wird mir die Datei zwar auch Angelegt, aber ohne Inhalt.

    VB.NET-Quellcode

    1. ​Private MyTable As DataTable
    2. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    3. Me.MyTable = Me.InitDataTable()
    4. Me.InitData()
    5. End Sub
    6. Private Function InitDataTable() As DataTable
    7. Dim table = New DataTable("TestDaten")
    8. ' für das DGV
    9. table.Columns.Add(New DataColumn("ID", GetType(Int32)))
    10. table.Columns.Add(New DataColumn("Account", GetType(String)))
    11. table.Columns.Add(New DataColumn("Webseite", GetType(String)))
    12. table.Columns.Add(New DataColumn("Benutzername", GetType(String)))
    13. table.Columns.Add(New DataColumn("Passwort", GetType(String)))
    14. Return table
    15. End Function
    16. Private Sub InitData()
    17. ' DataSource löschen
    18. Me.MyTable.Clear()
    19. Me.dgv.DataSource = Nothing
    20. End Sub
    21. Private Sub Btnsave_Click(sender As Object, e As EventArgs) Handles Btnsave.Click
    22. Me.MyTable.WriteXml("passwortliste.xml")
    23. Me.InitData()
    24. End Sub
    25. Private Sub Btnload_Click(sender As Object, e As EventArgs) Handles Btnload.Click
    26. Try
    27. Me.MyTable.ReadXml("passwortliste.xml")
    28. Catch ex As Exception
    29. MessageBox.Show("no or wrong data available")
    30. End Try
    31. End Sub

    Andy2002 schrieb:

    Me.MyTable.Clear()
    Warum löschst Du den Inhalt der DataTable inklusive aller angelegten Column, nachdem Du diese gerade erst erstellt hast???
    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.
    Und wo in Deinem Code ist jetzt die Verknüpfung zwischen DGV und DataTable?
    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.
    @VaporiZed Hatternich verstanden und folglich falsch abgeschrieben.
    @Andy2002 Folgender Ablauf:
    - alles löschen
    - Tabelle instialisieren
    - Tabelle aus XML lesen ODER Tabelle anderweitig befüllen
    - Tabelle dem DGV als DataSource zuweisen.
    Feddich.
    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!

    Andy2002 schrieb:

    Es gibt hier wohl nicht genügend Fachwissen, die das Problem beheben können
    Ich nehme vorerst einmal an, dass du das ohne Bedacht geschrieben hast und schon sehr müde warst...
    Ich will dich hier nur an meinen Post #3 erinnern, den du - glaube ich - überlesen hast...
    ​Ja ich Schreibe die Daten in die dgv über das Programm rein..
    So etwas macht man via Datatable und nicht über das DGV - trenne GUI und Daten! Das DGV ist an die Daten gebunden!

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

    Ja Müde trifft es.. Dennoch ich hab meine Lösung gefunden.. Ohne XML, klappt genau so wie ich es wollte.. Ist zwar etwas Mehr Code als die XML Variante. Aber das Stört recht wenig.

    ​So etwas macht man via Datatable und nicht über das DGV - trenne GUI und Daten! Das DGV ist an die Daten gebunden!


    Aber genau das muss ja gehen, schließlich sind mir die Daten Unbekannt, die der Nutzer dort Einträgt.. Und eine Datatable hatte ich drin. Siehe ersten Post.
    Nur muss es Möglich sein, Daten eben über die GUI "reinzuschreiben". Diese dann Speichern, und Laden. Beim Laden sollten die genau so wieder geladen werden, und falls der Nutzer Änderungen macht, sollten diese ebenfalls übernommen werden.
    Hier meine Lösung.. Sie Funktioniert. Ich bin Zufrieden.

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports System.Net
    4. Public Class Form2
    5. Dim W As IO.StreamWriter
    6. Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    7. End Sub
    8. Private Sub BtnUpdate_Click(sender As Object, e As EventArgs) Handles BtnUpdate.Click
    9. With ListView1.Items
    10. Dim item As ListViewItem
    11. item = .Add(idtxt.Text)
    12. item.SubItems.Add(acctxt.Text)
    13. item.SubItems.Add(wetxt.Text)
    14. item.SubItems.Add(benutzertxt.Text)
    15. item.SubItems.Add(passwtxt.Text)
    16. End With
    17. End Sub
    18. Private Sub Btnload_Click(sender As Object, e As EventArgs) Handles Btnload.Click
    19. Dim rtb As New RichTextBox
    20. rtb.Text = IO.File.ReadAllText("Accountdaten.txt")
    21. Dim i As Integer = 0
    22. For Each line As String In rtb.Lines
    23. If line = "--" Then
    24. Dim item As New ListViewItem With {
    25. .Text = rtb.Lines(i + 1)
    26. }
    27. item.SubItems.Add(rtb.Lines(i + 2))
    28. item.SubItems.Add(rtb.Lines(i + 3))
    29. item.SubItems.Add(rtb.Lines(i + 4))
    30. item.SubItems.Add(rtb.Lines(i + 5))
    31. ListView1.Items.Add(item)
    32. Else
    33. End If
    34. i += 1
    35. Next
    36. End Sub
    37. Private Sub Btnsave_Click(sender As Object, e As EventArgs) Handles Btnsave.Click
    38. Dim rtb As New RichTextBox
    39. For Each saveitem As ListViewItem In ListView1.Items
    40. rtb.AppendText("--" & vbNewLine & saveitem.Text & vbNewLine & saveitem.SubItems(1).Text & vbNewLine & saveitem.SubItems(2).Text & vbNewLine & saveitem.SubItems(3).Text & vbNewLine & saveitem.SubItems(4).Text & vbNewLine)
    41. Next
    42. rtb.SaveFile("Accountdaten.txt", RichTextBoxStreamType.PlainText)
    43. End Sub

    Andy2002 schrieb:

    Ja ich Schreibe die Daten in die dgv über das Programm rein.
    Trenne die Daten von der GUI...

    Andy2002 schrieb:

    Nur muss es Möglich sein, Daten eben über die GUI "reinzuschreiben".
    Ja - Und das bedeutet eine Benutzerinteraktion über das DGV und für so etwas ist ja geschaffen worden. Verstehst du da den Unterschied, was ich meine?
    Und warum steigst du jetzt vom richtigen Control in ein ListView um, dass man nicht an die Daten binden kann?
    @RodFromGermany hatte schon geschrieben, dass @Andy2002 es nicht verstanden hat. Und hat er wirklich nicht.
    Aber dafür gibt es ja seine Aussagen, dass es hier kein bzw. ungenügend Fachwissen gäbe..

    Vielleicht tut sich @Andy2002 ja mal die Tutorials hier im Forum an. Vielleicht arbeitet der OP ja mal sowas hier durch: die vier Views auf Video
    Hier gibt es durchaus sehr viel Fachwissen, bereitsgestellt von Forumsmitlgliedern die anderen immer wieder gern bereits sind zu helfen. Nein, ich gehöre nicht zu dieser Elite, aber bei solchen Aussagen vergeht mir auch die Lust solche Statements widerlegen zu wollen.

    VB1963 schrieb:

    Und warum steigst du jetzt vom richtigen Control in ein ListView um, dass man nicht an die Daten binden kann?


    Listview wollte ich eigentlich nicht nehmen, da ich schon so oft eben diesen weg gegangen bin.. Aber mit dem DataGridView, hab ich eben 0 Erfahrung.. Und Müde es aus dem Buch abzutippen, hier und da mal was von euch Nutzen, hat mir nichts gebracht, es lief nicht und der Abgabetermin kam immer näher. Also zurück zu dingen die ich kann. Und warum nicht gebunden?? Die Daten sind gebunden. User können nun Ihre Daten über Textboxen einfügen. Speichern und Laden, ggf. Ändern und neu Speichern.. Mehr sollte das DGV auch nicht tun..
    Du verstehst das Binden eines Controls an Daten nicht. Ein Control kann per Datasource an eine Datenquelle gebunden sein, wo deine Daten dann fürs Weiterarbeiten gehalten werden (späteres Speichern etc.). Wenn ein Benutzer Daten in ein Control eingibt, spricht man nicht von Datenbinding sondern das ist eine reine Benutzerinteraktion mit dem Control und hat gar nichts mit Datenbinding zu tun. Das musst du schon auseinanderhalten können!
    Schau mal da rein, da geht's ums Gleiche:
    Datagridview füllen
    Dieser TE hat es verstanden und beraten lassen ;)

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

    Hallo Andy,

    den Post mit der mangelnden Kompetenz überlese ich jetzt großzügig. Da dir offenbar komplett die Basics fehlen, habe ich dir ein funktionierendes Codebeispiel erstellt anhand dessen du alles verstehen kannst, was meine Vorgänger versucht haben dir zu erklären. Darüberhinaus habe ich auch das Prinzip XML-Serialisierung mit eingebracht, denn wenn schon XML dann bitte auch serialisieren.

    Bitte betrachte das nicht als Gelegenheit für Copy + Paste sondern versuche die folgenden Punkte darin zu verstehen und zu verinnerlichen:
    - das Binding der Accountliste and das Datagridview über den DataPropertyName
    - das Vermeiden von For-Each-Schleifen und For-Schleifen über LINQ (Performance-Vorteil)
    - XML-Serialisierung
    - korrekte Initialisierung

    Wenn du Fragen hast, dann melde dich gerne.

    Zunächst erstellst du dir eine neue Klasse

    Klasse

    VB.NET-Quellcode

    1. Imports System.Xml.Serialization
    2. <Serializable>
    3. Public Class Account
    4. <XmlElement(ElementName:="Accountname")>
    5. Public Property Accountname As String
    6. <XmlElement(ElementName:="Webseite")>
    7. Public Property Webseite As String
    8. <XmlElement(ElementName:="Benutzer")>
    9. Public Property Benutzer As String
    10. <XmlElement(ElementName:="Passwort")>
    11. Public Property Passwort As String
    12. Public Function GetSerializer() As XmlSerializer
    13. Return New XmlSerializer(Me.GetType)
    14. End Function
    15. End Class


    Hier der Code für deine Form:

    Form

    VB.NET-Quellcode

    1. Imports System.Xml.Serialization
    2. Imports System.IO
    3. Imports System.Text
    4. Public Class Accountverwaltung
    5. <XmlArray(ElementName:="Accounts")>
    6. Private Property Accountliste As List(Of Account)
    7. Private ActiveAccount As Account
    8. Private Filename As String = "C:\Temp\Text.xml"
    9. Private Sub Accountverwaltung_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    10. FormatAccountansicht()
    11. If Accountliste IsNot Nothing Then
    12. Accountdatenansicht.DataSource = Accountliste.ToArray
    13. Else
    14. Accountdatenansicht.DataSource = Nothing
    15. End If
    16. End Sub
    17. Private Sub Write()
    18. If File.Exists(Filename) Then
    19. File.Delete(Filename)
    20. End If
    21. Dim Serializer As XmlSerializer = New XmlSerializer(Accountliste.GetType)
    22. Dim XStream As StreamWriter
    23. Dim EmptyNamespace As New XmlSerializerNamespaces()
    24. EmptyNamespace.Add("", "")
    25. Using FileStream As New FileStream(Filename, FileMode.Create)
    26. XStream = New StreamWriter(FileStream, Encoding.UTF8)
    27. Serializer.Serialize(XStream, Accountliste, EmptyNamespace)
    28. FileStream.Close()
    29. End Using
    30. End Sub
    31. Private Sub Read()
    32. If Accountliste Is Nothing Then
    33. Accountliste = New List(Of Account)
    34. End If
    35. Dim Serializer As XmlSerializer = New XmlSerializer(Accountliste.GetType)
    36. Dim EmptyNamespace As New XmlSerializerNamespaces()
    37. EmptyNamespace.Add("", "")
    38. Using FileStream As New FileStream(Filename, FileMode.Open)
    39. Accountliste = Serializer.Deserialize(FileStream)
    40. FileStream.Close()
    41. End Using
    42. End Sub
    43. Private Sub btnImport_Click(sender As Object, e As EventArgs) Handles btnImport.Click
    44. If File.Exists(Filename) Then
    45. Read()
    46. UpdateAccountansicht()
    47. Else
    48. Accountdatenansicht.DataSource = Nothing
    49. End If
    50. End Sub
    51. Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
    52. If Accountliste IsNot Nothing Then
    53. Write()
    54. End If
    55. End Sub
    56. Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles Delete.Click
    57. If Accountdatenansicht.CurrentRow IsNot Nothing Then
    58. Accountliste.Remove(ActiveAccount)
    59. UpdateAccountansicht()
    60. End If
    61. End Sub
    62. Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
    63. If Accountliste Is Nothing Then
    64. Accountliste = New List(Of Account)
    65. End If
    66. Accountliste.Add(New Account With {.Accountname = String.Empty,
    67. .Webseite = String.Empty,
    68. .Benutzer = String.Empty,
    69. .Passwort = String.Empty})
    70. UpdateAccountansicht()
    71. End Sub
    72. Private Sub Accountdatenansicht_SelectionChanged(sender As Object, e As EventArgs) Handles Accountdatenansicht.SelectionChanged
    73. If Accountdatenansicht.CurrentRow IsNot Nothing Then
    74. ActiveAccount = Accountdatenansicht.CurrentRow.DataBoundItem
    75. End If
    76. End Sub
    77. Private Sub FormatAccountansicht()
    78. Accountdatenansicht.Columns.Clear()
    79. Accountdatenansicht.DataSource = Nothing
    80. Accountdatenansicht.AutoGenerateColumns = False
    81. Accountdatenansicht.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None
    82. Accountdatenansicht.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
    83. Accountdatenansicht.AllowUserToResizeColumns = True
    84. Accountdatenansicht.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
    85. Accountdatenansicht.AllowUserToAddRows = False
    86. Accountdatenansicht.AllowUserToDeleteRows = False
    87. Accountdatenansicht.SelectionMode = DataGridViewSelectionMode.CellSelect
    88. Accountdatenansicht.MultiSelect = False
    89. Accountdatenansicht.ScrollBars = ScrollBars.Both
    90. Accountdatenansicht.Columns.Add(New DataGridViewTextBoxColumn With {.Name = "Accountname", .DataPropertyName = "Accountname"})
    91. Accountdatenansicht.Columns.Add(New DataGridViewTextBoxColumn With {.Name = "Webseite", .DataPropertyName = "Webseite"})
    92. Accountdatenansicht.Columns.Add(New DataGridViewTextBoxColumn With {.Name = "Benutzer", .DataPropertyName = "Benutzer"})
    93. Accountdatenansicht.Columns.Add(New DataGridViewTextBoxColumn With {.Name = "Passwort", .DataPropertyName = "Passwort"})
    94. With Accountdatenansicht.Columns("Accountname")
    95. .ReadOnly = False
    96. .Visible = True
    97. .Width = 120
    98. .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
    99. .HeaderText = "Accountname"
    100. .SortMode = DataGridViewColumnSortMode.Automatic
    101. End With
    102. With Accountdatenansicht.Columns("Webseite")
    103. .ReadOnly = False
    104. .Visible = True
    105. .Width = 240
    106. .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
    107. .HeaderText = "Webseite"
    108. .SortMode = DataGridViewColumnSortMode.Automatic
    109. End With
    110. With Accountdatenansicht.Columns("Benutzer")
    111. .ReadOnly = False
    112. .Visible = True
    113. .Width = 120
    114. .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
    115. .HeaderText = "Benutzer"
    116. .SortMode = DataGridViewColumnSortMode.Automatic
    117. End With
    118. With Accountdatenansicht.Columns("Passwort")
    119. .ReadOnly = False
    120. .Visible = True
    121. .Width = 120
    122. .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft
    123. .HeaderText = "Passwort"
    124. .SortMode = DataGridViewColumnSortMode.Automatic
    125. End With
    126. End Sub
    127. Public Sub UpdateAccountansicht()
    128. Accountdatenansicht.DataSource = Nothing
    129. Accountdatenansicht.DataSource = Accountliste
    130. End Sub
    131. End Class



    Änderungen an den Objekten kannst du über das ActiveAccount-Objekt realisieren. Das ist immer das Objekt, dass im DataGridView ausgewählt ist. Das ActiveAccount-Objekt Teil der DataSource vom DatagridView ist, werden die Änderung an diesem Object direkt ins DatagridView übertragen, was von Vorteil ist, wenn du nicht direkt im DatagridView arbeitest sondern für die Bearbeitung Textboxen verwendest


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

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

    Yanbel schrieb:

    habe ich dir ein funktionierendes Codebeispiel erstellt


    Frage, der Code ist ja wie aus dem Buch.. :D Aber wo kann ich als Eingabe Textboxen Realisieren? Hier wird ja direkt auf die gdv geschrieben.. Und was ist ein ActiveAccount- Objekt?? Wegen Zeit Mangel hab ich deinen Code noch nicht getestet, oder aufgeschlüsselt. (hab nur gesehen das ich da 3 Buttons brauche..) Aber der Zug ist eh Abgefahren.. Ob ich je wieder was mit XML mache weiß ich ehrlich nicht..


    Habs mal getestet.. Also beim Löschen kommt..
    System.IndexOutOfRangeException: "Der Index 0 hat keinen Wert."
    Und zwar hier..

    VB.NET-Quellcode

    1. Private Sub Accountdatenansicht_SelectionChanged(sender As Object, e As EventArgs) Handles Accountdatenansicht.SelectionChanged
    2. If Accountdatenansicht.CurrentRow IsNot Nothing Then
    3. ActiveAccount = Accountdatenansicht.CurrentRow.DataBoundItem
    4. End If
    5. End Sub


    *Vollzitat entfernt* ~NoFear23m

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

    Beispiel:

    VB.NET-Quellcode

    1. tbAccountname.Text = ActiveAccount.Accountname
    2. tbWebseite.Text = ActiveAccount.Webseite


    Geht natürlich auch in die andere Richtung.

    Nein, es wird nirgendwo ins Datagrid geschrieben. Du arbeitest ausschließlich mit der Accountliste, also der Datasource vom DatagridView.

    Es geht nicht um XML, sondern um das Prinzip des Databindings.

    Die Exception habe ich nicht abgefangen. Passiert natürlich wenn kein Objekt mehr in der Liste ist.

    VB.NET-Quellcode

    1. If Accountdatenansicht.CurrentRow IsNot Nothing Then


    Mach daraus mal bitte:

    VB.NET-Quellcode

    1. If Accountliste isNot Nothing Andalso Accountliste.Count > 0 AndAlso Accountdatenansicht.CurrentRow IsNot Nothing Then




    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

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