Objektorientiert einer ComboBox einen Wert zuweisen

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

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

    Objektorientiert einer ComboBox einen Wert zuweisen

    Hallo,

    für mein Studium muss ich ein Projekt erarbeiten und stoße dabei auf ein Problem

    Ich habe eine Klasse Produktgruppe und diese in einem Formular darüber instanziert.

    VB.NET-Quellcode

    1. Private Property PGRListe As New List(Of Produktgruppe)


    Gefüllt wird diese Liste wie folgt und wenn diese gefüllt ist, dann soll diese die Datenquelle einer ComboBox darstellen. Das klappt alles soweit einwandfrei.

    VB.NET-Quellcode

    1. Dim Connection As New OleDbConnection(Variablen.ConnectionString)
    2. Dim Command As New OleDbCommand("SELECT * FROM stblProduktgruppe", Connection)
    3. Dim Reader As OleDbDataReader
    4. Try
    5. Connection.Open()
    6. Reader = Command.ExecuteReader
    7. While Reader.Read
    8. PGRListe.Add(New Produktgruppe(Reader("GruppenID").ToString, Reader("Bezeichnung").ToString))
    9. End While
    10. Reader.Close()
    11. Combo.DataSource = PGRListe
    12. Combo.DisplayMember = "Bezeichnung"
    13. Catch ex As Exception
    14. Mitteilung.ZeigeMeldung("Upps, hier ist etwas schief gegangen!" & vbNewLine & "Bitte im Protokoll nachlesen.", Mitteilung.Warnstufe.Fehler)
    15. Mitteilung.SchreibeSQLProtokoll(ex.Message, Me.GetType().Name, System.Reflection.MethodBase.GetCurrentMethod().Name)
    16. Finally
    17. Connection.Close()
    18. End Try


    Schwierig wird es allerdings, wenn ich jetzt einen konkreten Artikel mir anzeigen lassen möchte, also auch eine konkrete Produktgruppe habe.

    VB.NET-Quellcode

    1. Me.cboProduktgruppe.SelectedItem.ID = Artikelliste.ElementAt(Me.ArtIndex).GruppenID


    Es passiert auf dem Formular nichts, er zeigt nach wie vor den ersten Eintrag an, gleichwohl er wenn ich mir SelectedItem-Eigenschaft abrufe ich den richtigen Wert zurück bekomme.
    Die Daten in ...GruppenID stimmen exakt mit dem jeweiligen Artikel da steht drin "K"c drin (die ID ist bei uns ein Char)

    Kann mir da einer aufs Pferd helfen?
    Wie genau ist

    kurzda schrieb:

    Produktgruppe
    deklariert?
    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!
    Hallo @kurzda,

    verwende zusätzlich zum DisplayMember auch den ValueMember. Dann hat die Reihenfolge der Elemente in der Combobox auch keinen Einfluss auf die Auswahl, wenn du die GruppenID als ValueMember verwendest. Also in deinem Fall:

    VB.NET-Quellcode

    1. ​ComboBox1.DataSource = PGRListe
    2. ComboBox1.DisplayMember = "Bezeichnung"
    3. ComboBox1.ValueMember = "GruppenID"


    kurzda schrieb:

    Schwierig wird es allerdings, wenn ich jetzt einen konkreten Artikel mir anzeigen lassen möchte, also auch eine konkrete Produktgruppe habe.

    Ich verstehe diese Aussage leider nicht ganz. Vermutlich willst du ein bestimmtes Element in deiner ComboBox selektieren. Ansonsten lass mich bitte wissen, was du genau machen willst :)

    Eine Auswahl eines bestimmten Items erfolgt jetzt über die GruppenID.

    VB.NET-Quellcode

    1. ​ComboBox1.SelectedValue = "K"c ' oder welche ID du auch immer anwählen willst


    Die Ermittlung des aktuell angewählten Items sowie das Auslesen dessen Eigenschaften erfolgt über das SelectedItem. Group ist dabei die Klasse, welche du für eine Produktgruppe angelegt hast.

    VB.NET-Quellcode

    1. ​Dim g As Group = CType(ComboBox1.SelectedItem, Group)

    g ist nun eine Produktgruppe und von diesem Objekt kannst du die gewünschten Eigenschaften lesen und weiterverarbeiten.

    LG Switcherlapp97
    RubiksCubeSolver


    Jetzt im Showroom
    @RodFromGermany
    Also die Produktgruppe ist wie folgt deklariert

    VB.NET-Quellcode

    1. Public Class Produktgruppe
    2. Public Property ID As Char
    3. Public Property Bezeichnung As String
    4. Public Sub New(ID As Char, Bezeichnung As String)
    5. Me.ID = ID
    6. Me.Bezeichnung = Bezeichnung
    7. End Sub
    8. End Class


    @Switcherlapp97
    Genau das ist mein Ziel in der ComboBox entsprechendes auszuwählen. Im übrigen wenn ich den ValueMember angebe, erhalte ich folgende Fehlermeldung.

    Quellcode

    1. An den neuen Wertemember kann nicht gebunden werden.
    2. Parametername: value


    Grundsätzlich werden die Felder der Klasse übernommen, so kann ich auch den aktuellen Wert der ComboBox abfragen
    Combo1.SelectedItem.ID => mit ID ist das Property aus Klasse gemeint und ist auch korrekt gefüllt mit "K"c
    Du musst beim ValueMember die genaue Property-Bezeichnung nehmen. Die Property heißt bei dir "ID" und nicht wie ich zuerst erwartet habe "GruppenID".
    RubiksCubeSolver


    Jetzt im Showroom
    @kurzda Meinst Du so was (Form mit drei Button und einer ComboBox):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private ll As New List(Of Produktgruppe)
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. ll.Add(New Produktgruppe("a"c, "aa"))
    5. ll.Add(New Produktgruppe("b"c, "bb"))
    6. ll.Add(New Produktgruppe("c"c, "cc"))
    7. ll.Add(New Produktgruppe("d"c, "dd"))
    8. Me.ComboBox1.DataSource = ll
    9. ' hier kein DisplayMember
    10. End Sub
    11. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    12. Me.ComboBox1.DisplayMember = "ID"
    13. End Sub
    14. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    15. Me.ComboBox1.DisplayMember = "Bezeichnung"
    16. End Sub
    17. End Class
    18. Public Class Produktgruppe
    19. Public Property ID As Char
    20. Public Property Bezeichnung As String
    21. Public Sub New(ID As Char, Bezeichnung As String)
    22. Me.ID = ID
    23. Me.Bezeichnung = Bezeichnung
    24. End Sub
    25. End Class

    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 bin zwar nicht zu Hause wo ich das testen könnte, sieht aber schon gut aus und klingt logisch. Der Sauberkeit halber werde ich aber noch die Property ID in GruppenID umbenennen. Da habe ich wohl nicht aufgepasst ;)

    Einzig bei @RodFromGermany glaube ich, dass damit nicht das Ziel erreicht wird oder ich habe einen Hänger beim Denken gerade.

    Ich habe vorher ja alle möglichen Produktgruppen in die Liste PGRListe gefüllt und diese als Datenquelle der ComboBox verwendet => klappt und ist in Ordnung!

    VB.NET-Quellcode

    1. Me.cboProduktgruppe.SelectedItem.ID = Artikelliste.ElementAt(Me.ArtIndex).GruppenID


    Mit diesem Code möchte ich jetzt aus der Liste Artikelliste vom Element mit dem Index xy die zugehörige GruppenID zur ComboBox übergeben, sodass bei der konkreten Artikelbearbeitung (ich habe einen konkreten Artikel aufgerufen mit artikelspezifischen Informationen) dessen Eigenschaften angezeigt wird. Im Hintergrund scheint die ComboBox mit meinem obigen Code auch zu funktionieren, sie nimmt den zumindest Wert an, jedoch zeigt er mir im Formular selber immer nur den ersten Eintrag in der Liste an, nie den richtigen Wert der auch zum Artikel passt.
    @kurzda So was, nach Button1, nach Button2, nach Button3:

    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!
    ja @RodFromGermany das sieht schon gut aus. Die Daten werden ja erfolgreich auch gefüllt.

    Standardmäßig ist ja der SelectedIndex am Anfang = 0 und damit bei dir der Wert a/aa

    Jetzt gucke ich mir einen Artikel im Detail an und der hat die Produktgruppe c/cc. Die Schwierigkeit war, dass ich der ComboBox zwar sagen konnte, dass der Artikel c/cc ist, er zeigte jedoch weiterhin als ausgewählten Wert a/aa an. Wenn ich die ComboBox NACH der Zuweisung vom Artikel abfrage, dann steht als SelectedItem auch c/cc drin, sehen tue ich aber nur a/aa.
    Mir ist unklar, was du erreichen willst, weil eine datengebundene Combo kann man auf 2 Weisen einsetzen, wenn eine 1:n - Relation gegeben ist, und das trifft bei ProduktGruppe->Artikel ja zu.
    1. Die Combo wählt eine Gruppe aus, und ein anderes ListenControl zeigt alle Artikel dieser Gruppe (Parent-Child-View)
    2. Das ListenControl zeigt alle Artikel wild durcheinander, aber wenn man einen Artikel anwählt, so springt die Combo auf die entsprechende Gruppe. (Joining-View)
    Was du wolle?

    kurzda schrieb:

    SelectedItem
    ==> SelectedIndex?
    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!
    @RodFromGermany danke für den Tipp, aber da verstehe ich zwei Dinge nicht. Was für ein Unterschied macht das und ich kenne doch den Index gar nicht. Ich speichere im Artikel doch nur ob dieser a oder b oder c ist.

    @ErfinderDesRades okay ich scheine mich wirklich falsch ausgedrückt zu haben.
    Ich habe in einem DGV alle Artikel aufgelistet. Ich mach dann auf einen Artikel einen Doppelklick und möchte mir jetzt alle Details von genau einem Artikel anschauen. In diesem Moment ist der Tupel Artikel mit den verschiedenen Attributen aus anderen Tabellen in einer 1:1 Beziehung. Klar in der Realität ist es eine 1:n Beziehung.

    Auf dem Artikeldetailblatt will ich jetzt für einen konkreten Artikel alle Informationen anzeigen. Wie heißt er, welche Preise hat er und in welcher Produktgruppe befindet sich er. Beim Form_Load befülle ich alle "Auswahl"-Controls mit den möglichen Daten. Beim Artikelladen wähle ich aus den bereits gefüllten Controls nur noch die passenden Werte aus.

    Ich hoffe das war jetzt verständlich ;)

    kurzda schrieb:

    Ich habe in einem DGV alle Artikel aufgelistet. Ich mach dann auf einen Artikel einen Doppelklick und möchte mir jetzt alle Details von genau einem Artikel anschauen.
    Ich denke, ich habe dich sehr genau verstanden, womöglich besser als die Beschreibung, die du gibst.

    Egal
    guggemol auf vier Views-Videos den DEtailView-Film, da kommt eine Joining-Combo vor.
    Oder guck einfach alle 4 Views, da sollte in jedem Fall was passendes dabei sein.
    @kurzda Mach ein NumericUpDown auf die GUI zu meinem Code von Post #6 (Maximum beachten) und dann dies:

    VB.NET-Quellcode

    1. Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
    2. Me.ComboBox1.SelectedItem = ll(CInt(NumericUpDown1.Value))
    3. 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!
    @RodFromGermany Danke für den Anstupser zum Denken, ich habe die Lösung gefunden. Ist mehr Programmieraufwand, aber ich habe die Lösung und sie funktioniert!!!!! Auch euch @ErfinderDesRades @Switcherlapp97 Danke das ihr mir dabei helfen wolltet!

    Ich glaube Ursache meines Problems war, dass ich noch nicht ganz OOP denke ;) Das SelectedItem empfängt nicht einen konkreten Wert sondern ein ganzes Objekt und zwar das ausgewählte Objekt aus der PGRListe. Ich muss vorher den Index der beim Artikel hinterlegten Produktgruppe in der PGRListe suchen und übergebe das Objekt anschließend an die ComboBox.

    Hier mal mein Code samt Formular, was ich gerade Testweise zusammen gezimmert habe.



    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim Artikelliste As New List(Of Artikel)
    2. Dim PGRListe As New List(Of Produktgruppe)
    3. Dim KATListe As New List(Of Produktkategorie)
    4. Private Property ArtIndex As Integer
    5. Private Property PGRIndex As Integer
    6. Private Property KATIndex As Integer
    7. Private Sub frm_SpecialMode_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    8. GruppeFüllen()
    9. KategorieFüllen()
    10. ArtikelFüllen()
    11. End Sub
    12. Private Sub ArtikelFüllen()
    13. Artikelliste.Add(New Artikel("A1", "Artikel 1", "a"c, 100))
    14. Artikelliste.Add(New Artikel("A2", "Artikel 2", "a"c, 100))
    15. Artikelliste.Add(New Artikel("A3", "Artikel 3", "b"c, 200))
    16. Artikelliste.Add(New Artikel("A4", "Artikel 4", "b"c, 200))
    17. Artikelliste.Add(New Artikel("A5", "Artikel 5", "c"c, 300))
    18. Artikelliste.Add(New Artikel("A6", "Artikel 6", "c"c, 300))
    19. Artikelliste.Add(New Artikel("A7", "Artikel 7", "d"c, 400))
    20. Me.DataGridView1.DataSource = Artikelliste
    21. End Sub
    22. Private Sub GruppeFüllen()
    23. PGRListe.Add(New Produktgruppe("a"c, "Gruppe a"))
    24. PGRListe.Add(New Produktgruppe("b"c, "Gruppe b"))
    25. PGRListe.Add(New Produktgruppe("c"c, "Gruppe c"))
    26. PGRListe.Add(New Produktgruppe("d"c, "Gruppe d"))
    27. PGRListe.Add(New Produktgruppe("e"c, "Gruppe e"))
    28. Me.ComboBox1.DataSource = PGRListe
    29. Me.ComboBox1.DisplayMember = "Bezeichnung"
    30. Me.ComboBox1.ValueMember = "GruppenID"
    31. End Sub
    32. Private Sub KategorieFüllen()
    33. KATListe.Add(New Produktkategorie(100, "Kategorie 100", "a"c))
    34. KATListe.Add(New Produktkategorie(200, "Kategorie 200", "b"c))
    35. KATListe.Add(New Produktkategorie(300, "Kategorie 300", "c"c))
    36. KATListe.Add(New Produktkategorie(400, "Kategorie 400", "d"c))
    37. KATListe.Add(New Produktkategorie(500, "Kategorie 500", "e"c))
    38. Me.ComboBox2.DataSource = KATListe
    39. Me.ComboBox2.DisplayMember = "Bezeichnung"
    40. Me.ComboBox2.ValueMember = "KatID"
    41. End Sub
    42. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    43. Me.ArtIndex = (Artikelliste.FindIndex(Function(value As Artikel)
    44. Return value.ArtID = Me.DataGridView1.SelectedRows(0).Cells(0).Value.ToString
    45. End Function))
    46. Me.PGRIndex = PGRListe.FindIndex(Function(value As Produktgruppe)
    47. Return value.GruppenID = Me.Artikelliste.ElementAt(Me.ArtIndex).GruppenID
    48. End Function)
    49. Me.KATIndex = KATListe.FindIndex(Function(value As Produktkategorie)
    50. Return value.KatID = Me.Artikelliste.ElementAt(Me.ArtIndex).Kategorie
    51. End Function)
    52. Me.TextBox1.Text = Artikelliste.ElementAt(ArtIndex).ArtID
    53. Me.TextBox2.Text = Artikelliste.ElementAt(ArtIndex).ArtBez
    54. Me.ComboBox1.SelectedItem = PGRListe.ElementAt(PGRIndex)
    55. Me.ComboBox2.SelectedItem = KATListe.ElementAt(KATIndex)
    56. End Sub
    Bilder
    • Lösung.JPG

      56,01 kB, 1.011×419, 1.110 mal angesehen
    Das ist jetzt Databinding so schlecht und recht nachgebastelt.
    Haste dir mal das DetailView-Video angeguckt?
    Weil wenn du mit dem richtigen Instrumentarium arbeitest, kann man sowas im Designer zurechtmachen.

    Die Videos (link in post#13) behandeln übrigens genau dein Thema, eine m:n-Relation, sind nur andere Bezeichnungen:

    Bei dir ists:
    ProduktGruppe->Artikel<-Kategorie

    Bei mir:
    Artikel->ArtikelLieferant<-Lieferant

    Aber jetzt fürs Studium hast du das Rad ja selbst neu erfunden - vmtl. langts für den Schein.
    Jedoch falls du iwie dran bleibst anne Proggerei empfähle ich, sich doch mal die vorgesehene Technologie anzugugge. Dahinter steht auch ein bischen Theorie (nämlich: "was ist eine Relation"?), aber ich hoffe, das wird in deim Studium klargemacht.
    Aber schadet auch nicht, dem diesbezüglichen (zur Theorie) weiterführenden Link zu folgen, meine Erklärungen dazu sind glaub leichter verständlich als so manche Vorlesung.
    @ErfinderDesRades ist das echt schlechte Programmierung??? So ähnlich lerne ich es in der Schule. Was ich nicht machen wollte ist eine feste Datenbindung, also das Programm kennt die Datenbank an sich nicht. Sie weiß nur, dass es sie gibt und kopiert mir sie mit ins Ausgabeverzeichnis (ist eine Access-Datenbank).

    Die Videos habe ich mir noch nicht anschauen können, werde ich aber noch tun, ich will schon sauber und vernünftig programmieren.
    ja, ziemlich schlecht.
    Aber das Thema Schule/Ausbildung/Studium ist eh höchst brisant. Ich höre total viel von Lehr-Veranstaltungen, die eiglich verboten gehören.

    Und guck dir erst die Videos an, und arbeite dich in Databinding ein. Weil wie du den Begriff verwendest, so ist er nicht definiert.
    Databinding hat mit Datenbanken garnix zu tun - es ist was ganz ganz anderes, und ob ein Programm eine Datenbank kennt, oder nicht, oder ob ühaupt eine existiert, ist für Databinding irrelevant.

    DatenModellierung ist der Punkt - und da hast du mit deiner selbstgebastelten ProduktGruppe-Klasse schon ein klein Anfang gemacht.
    Nur sind selbstgebastelte Klassen ungeeignet, um m:n-Relationen darzustellen.

    Naja, nicht zwingend ungeeignet, aber es gibt Technologien, zB typisiertes Dataset, das bietet ganz unvorstellbare Möglichkeiten, also wörtlich gemeint: Wenn mans nicht gesehen hat, kann man sich das nicht vorstellen.
    Ein grund mehr, die Videos zu gucken.
    ich habe mir einige Videos jetzt angeschaut und rätsel noch so vor mich her:
    • Ist es richtig, dass die Daten die dort generiert wurden, aus keiner Datenbank kommen sondern zur Laufzeit generiert werden?
    • Bezogen auf mein Projekt, wofür braucht man überhaupt noch Klassen, wenn am Ende alles aus einem DataSet kommt und man typisierte Dinge ableiten kann
    • Ohne groß jetzt eine Anleitung zu bekommen, konstruiert man sein ER-Modell neben der Datenbank auch komplett im DataSet?
    • Gibt es ein Buch woran ich sauberes & gutes Programmieren lernen kann?
      Die Videos waren sicherlich nicht schlecht, aber um es zu verstehen fehlten mir an der einen oder anderen Stelle noch Punkte
    Und im übrigen Frohe Ostern!!