Einlesen von Dictionary-Werten in Combobox

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ery.

    Einlesen von Dictionary-Werten in Combobox

    Hallo,

    ich versuche gerade eine Combobox mit KeyValue Pairs zu befüllen. Leider habe ich mehrere Werte die ich in der Combobox speichern muss (z.B. name, straße, etc.)
    Ich habe schon folgendes Versucht:

    VB.NET-Quellcode

    1. Module LoadCustomer
    2. Public Sub LoadCustomers()
    3. Dim Customers() As String
    4. Dim sr = My.Computer.FileSystem.OpenTextFileReader("customers\customers.txt", System.Text.Encoding.Unicode)
    5. Dim customerDict As New Dictionary(Of String, List(Of String))
    6. Dim CustomerList As New List(Of String)
    7. While sr.EndOfStream = False
    8. Customers = sr.ReadLine.Split(",")
    9. CustomerList.Add(Customers(1))
    10. CustomerList.Add(Customers(2))
    11. CustomerList.Add(Customers(3))
    12. CustomerList.Add(Customers(4))
    13. customerDict.Add(Customers(0), CustomerList)
    14. End While
    15. End Sub
    16. End Module

    Leider weiß ich nicht wie ich auf die CustomerList in der Combobox zugreifen kann... (und leider weiß ich auch nicht ob ich da überhaupt auf dem richtigen Weg bin.) Bitte um Info... Danke!


    Beste Grüße
    aber nützlich wäre glaub trotzdem, du würdest mehr erzählen, was das werden soll.
    Ich könnte mir vorstellen, in der Datei sind Datensätze, evtl. mit mehr als 2 Spalten - das würde eh nicht mehr richtig in Dictionaries reingehen.
    Aber so oder so enthält der gezeigte Code logische Fehler, aber solange nicht klar ist, was eiglich wirklich bezweckt wird, ...
    Auch ein kl. Auszug aus einer Beispiel-Datei könnte zur Klärung etwas beitragen.

    Am Ende ist ein Dictionary sogar ganz ungeeignet. Oder es ist zwar leidlich geeignet, es gäbe aber besseres. Oder oder oder...
    Okay, hier mal eine kurze Erklärung (bitte Bedenken, bin Anfänger und habe teilweise sicher etwas zusammengemurkst... :D):

    Ich habe verschiedene Forms in welche teilweise Kundendaten (Firmenname, Adresse, etc jeweils in einer Textbox) eingelesen werden (aus einer Textdatei vorerst, per "," getrennt, jede Zeile ist ein zusammengehöriger Satz) bzw. auch aus solchen beschrieben werden - letzteres ist auf diese Art ja zumindest kein Problem. Eine Datenbank scheint mir für diesen Zweck aber trotzdem überdimensioniert zu sein.
    In den Formularen, die die Kundendaten verwenden sollen, gibt es eine Combobox in welcher die Firmennamen (erster Wert in der Zeile der Textdatei) eingelesen werden sollen, beim Auswählen eines solchen sollen die Textfelder automatisch mit Vorgaben befüllt werden.
    Eine Möglichkeit hätte ich noch im Kopf. Ich befülle einfach ganz normal die Comboboxen mit den Werten und zähle dann einfach die Zeilen nach (je nachdem welcher Index gewählt ist) +1 für die Zeile, oder so ähnlich - das sieht mir aber nicht allzu sauber aus?!...

    Das wäre der Aufbau meiner Textdatei, wobei das ja eher nebensächlich ist, denke ich.

    Quellcode

    1. ​firma,uid,name,straße,plz,stadt
    Das Stichwort wäre hier...
    Dataset und Databinding.

    Dafür musst nur ein paar Zeilen Code schreiben.

    Ich denke der Erfinder wird dir gleich nen Tutorial verlinken ;D
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    ery schrieb:

    Quellcode

    1. firma,uid,name,straße,plz,stadt
    Das wäre der Aufbau meiner Textdatei, wobei das ja eher nebensächlich ist, denke ich.
    Im Gegenteil: die Daten sind das eigentlich wesentliche.

    Also du brauchst eindeutig spezielle Daten-Klassen, und am besten wäre wohl, du würdest dich mit relationaler Datenmodellierung beschäftigen - wärest du dazu bereit?
    (ah - hat Memo schon angesprochen - ich hab mich noch nicht getraut, und stattdessen das folgende Gesimpel zurechtgebastelt)

    jedenfalls eine Datenklasse könnte so aussehen:

    VB.NET-Quellcode

    1. Public Class Customer
    2. Public Property firma As String
    3. Public Property uid As String
    4. Public Property name As String
    5. Public Property straße As String
    6. Public Property plz As String
    7. Public Property stadt As String
    8. End Class
    Nun hast du überhaupt erst etwas, wohinein du deine Datei einlesen kannst

    VB.NET-Quellcode

    1. Public Function LoadCustomers() As List(Of Customer)
    2. Dim lst = New List(Of Customer)
    3. Using sr = My.Computer.FileSystem.OpenTextFileReader("customers\customers.txt", System.Text.Encoding.Unicode)
    4. Do
    5. Dim line = sr.ReadLine
    6. If line Is Nothing Then Return lst
    7. Dim splits = line.Split(","c), i = 0
    8. Dim cust = New Customer
    9. cust.firma = splits(i) : i += 1
    10. cust.uid = splits(i) : i += 1
    11. cust.name = splits(i) : i += 1
    12. cust.straße = splits(i) : i += 1
    13. cust.plz = splits(i) : i += 1
    14. cust.stadt = splits(i) : i += 1
    15. lst.Add(cust)
    16. Loop
    17. End Using
    18. End Function
    Und dann kannst du im Form auch eine Combo dran binden, damit du einen Customer davon auswählen kannst:

    VB.NET-Quellcode

    1. Private _Customers As List(Of Customer)
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    3. _Customers = LoadCustomers()
    4. ComboBox1.DataSource = _Customers
    5. ComboBox1.DisplayMember = "Firma"
    6. End Sub

    Also das ist noch ganz unzureichend, aber wenn du das ans Laufen kriegst, vlt. kommst du immerhin bischen auf den Geschmack.

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

    Ah, danke - da hast du bzw. ihr mich auf eine gut aussehende Spur gebracht...
    Ja, ohne zu wissen, was mich erwartet sage ich mal, ich bin dazu bereit... Lernen muss ich es früher oder später sowieso - und zumindest mal einen Überblick davon zu haben kann auch nicht schaden...

    Jetzt verstehe ich auch den Teil mit den Datenklassen aus meinem Buch (wurde zwar beschrieben wie es geht aber nicht wann man das brauchbar einsetzen kann...)

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

    So, habe das ganze hinbekommen. Danke für die Hilfe - ohne deinen Code hätte ich das wohl nicht so schnell geschafft, sogar das Verwalten der Einträge läuft schon (obwohl WriteAllText hier wohl nicht das performanteste ist :D)
    Hier der entsprechende Code für die Nachwelt:

    Einlesen der Configdatei
    Laden bzw. befüllen der Combobox

    VB.NET-Quellcode

    1. Private Sub LoadForm(Optional ByRef selectedindex As Integer = 0)
    2. _Customers = LoadCustomer.LoadCustomers()
    3. cmbKundenliste.DataSource = _Customers
    4. cmbKundenliste.DisplayMember = "Firma"
    5. cmbKundenliste.SelectedIndex = 0
    6. cmbKundenliste.SelectedIndex = selectedindex
    7. LaenderFuellen()
    8. End Sub


    Füllen der Textfelder, falls ein Eintrag ausgewählt wurde und speichern eines "Ursprung-Strings" für späteres verwenden

    VB.NET-Quellcode

    1. Private Sub cmbKundenliste_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbKundenliste.SelectedIndexChanged
    2. txtFirma.Text = _Customers.Item(cmbKundenliste.SelectedIndex).firma
    3. txtUID.Text = _Customers.Item(cmbKundenliste.SelectedIndex).uid
    4. txtEmpfaenger.Text = _Customers.Item(cmbKundenliste.SelectedIndex).name
    5. txtStraße.Text = _Customers.Item(cmbKundenliste.SelectedIndex).straße
    6. txtPLZ.Text = _Customers.Item(cmbKundenliste.SelectedIndex).plz
    7. txtStadt.Text = _Customers.Item(cmbKundenliste.SelectedIndex).stadt
    8. cmbLand.SelectedItem = _Customers.Item(cmbKundenliste.SelectedIndex).land
    9. searchstring = txtFirma.Text & "," & txtUID.Text & "," & txtEmpfaenger.Text & "," & txtStraße.Text & "," & txtPLZ.Text & "," & txtStadt.Text & "," & cmbLand.SelectedItem
    10. End Sub


    VB.NET-Quellcode

    1. Private Sub btnSpeichern_Click(sender As Object, e As EventArgs) Handles btnSpeichern.Click
    2. Dim replacestring = txtFirma.Text & "," & txtUID.Text & "," & txtEmpfaenger.Text & "," & txtStraße.Text & "," & txtPLZ.Text & "," & txtStadt.Text & "," & cmbLand.SelectedItem
    3. Dim findstring As String = My.Computer.FileSystem.ReadAllText("customers\customers.txt")
    4. If txtFirma.Text <> "" And txtUID.Text <> "" And txtEmpfaenger.Text <> "" And txtStraße.Text <> "" And txtPLZ.Text <> "" And txtStadt.Text <> "" And cmbLand.SelectedItem <> "" Then
    5. findstring = findstring.Replace(searchstring, replacestring)
    6. My.Computer.FileSystem.WriteAllText("customers\customers.txt", findstring, False)
    7. Dim selectedIndex = cmbKundenliste.SelectedIndex
    8. LoadForm(selectedIndex)
    9. Else
    10. End If
    11. End Sub


    VB.NET-Quellcode

    1. Module LoadCustomer
    2. Public Function LoadCustomers() As List(Of Customer)
    3. Dim lst = New List(Of Customer)
    4. Dim sr = My.Computer.FileSystem.OpenTextFileReader("customers\customers.txt", System.Text.Encoding.Unicode)
    5. Dim newc = New Customer
    6. lst.Add(newc)
    7. Do
    8. Dim line = sr.ReadLine
    9. If line Is Nothing Then
    10. sr.Close()
    11. Return lst
    12. End If
    13. Dim splits = line.Split(","c), i = 0
    14. Dim cust = New Customer
    15. cust.firma = splits(i) : i += 1
    16. cust.uid = splits(i) : i += 1
    17. cust.name = splits(i) : i += 1
    18. cust.straße = splits(i) : i += 1
    19. cust.plz = splits(i) : i += 1
    20. cust.stadt = splits(i) : i += 1
    21. cust.land = splits(i) : i += 1
    22. lst.Add(cust)
    23. Loop
    24. End Function
    25. Public Class Customer
    26. Public Property firma As String
    27. Public Property uid As String
    28. Public Property name As String
    29. Public Property straße As String
    30. Public Property plz As String
    31. Public Property stadt As String
    32. Public Property land As String
    33. End Class
    34. End Module


    Ich hoffe ich schaff sowas beim nächsten mal alleine. Was ich immer wieder vergesse ist, das ich den String nicht direkt überschreiben kann sondern immer "sich selbst zuweisen" muss (z.B.

    VB.NET-Quellcode

    1. findstring = findstring.Replace(searchstring, replacestring)
    )
    zu listing1: vermeide ByRef. Damit kann man sich u.U. ins Knie schiessen. ByRef hat manchmal seine Berechtigung, und wo nicht nötig immer die Finger davon lassen.
    zeile #5 kann weg - einmal den Index setzen reicht.

    Zu Listing#2: .Item ist eine Default-Property und lässte besser weg:

    VB.NET-Quellcode

    1. txtFirma.Text = _Customers(cmbKundenliste.SelectedIndex).firma
    _Customers ist zwar kein Array, aber es ist ebenso indizierbar wie ein Array, und da lässt man .Item halt weg.

    zu listing#3:
    Verwende besser den Using-Block, wie ich gezeigt habe. Geht natürlich in dem Falle auch so, weil .Close und .Dispose sind intern dieselbe Methode.
    Aber der Pattern ist halt der Dispose-Pattern, und da schadets nicht, wenn man den benutzt as usual (means: mit Using-Block)

    So, da sind jetzt paar Stichworte gefallen, die ich unerklärt liess (Using, ByRef, Dispose-Pattern, Default-Property, Array,...?). Wenn du ein Buch hast, oder sonstwie, tätich empfehlen, diese Stichworte zu recherchieren.
    Ich empfehle immer den Löffelmann2005 - da sind derlei Grundlagen glaub am gründlichsten durchgenommen. Kost nix, Links findeste inne Bücherliste: Entwickler-Ressourcen und Tools, Bücher und WebCasts

    ErfinderDesRades schrieb:

    zeile #5 kann weg - einmal den Index setzen reicht.

    Ich gebe aber nicht immer einen Wert mit, ich setze diesen nur damit ich einen anderen Wert in der Combobox ausgewählt habe (setzte einen Leer-Wert am Anfang in die Combobox), dieser Wird ggf überschrieben wenn ich die Form neu laden (nach dem Speichern --> LoadForm(selectedIndex) damit bleibt der aktuell bearbeitete ausgewählt.
    Nachtrag: Ich merke gerade, das ist ja Blödsinn - das ist wohl der Grund warum immer ein Wert zugewiesen werden muss. Danke fürs drauf aufmerksam machen...

    Oh, wusste nicht das ich auch ohne dem ".item" auf den Wert zugreifen kann...
    Den "Using" block kannte ich nicht und den habe ich - der einfachkeit halber - weggelassen. Werde ich mich mal einlesen.

    Das ByRef habe ich zum "Speichersparen" genutzt - obwohl das ja so gut wie nichts ausmacht, denke ich, und da ich den Wert ja nicht bearbeite habe ich das deshalb verwendet.

    Danke, den Link schau ich mir auch mal genauer an (bzw. gleich im Zuge der Recherche zu den obigen Themen)

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