Mehrere Spalten aus einer Combobox auslesen

  • VB.NET

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von stepper71.

    Mehrere Spalten aus einer Combobox auslesen

    Hallo,

    ich zeige in einer Combobox die Daten einer Tabelle über eine Bindingsource an.
    Den Member und den Wertemember habe ich festgelegt.
    In der Combobox wird nun die gewünschte Spalte angezeigt (z.B. Name des Kunden) und mit cboKundenID.SelectedValue erhalte ich den gewünschten Wertemember (z.B. KundenID).
    Soweit alles gut.

    Aber:
    Kann ich jetzt auch auf die anderen Spalten des gewählten Datensatz aus der Tabelle zugreifen?
    Beispiel: Die Tabelle enthält KundenID, KundenName, Kundenstatus, Kundentyp.
    Über combobox.selectedvalue erhalte ich die KundenID. Kann ich auf ähnliche weise auch die anderen Spalten abfragen?

    Gruß
    Stepper
    Bitte entschuldige, Macht der Gewohnheit.
    Ich war schon stolz das ich die Combobox über eine BindingSource und nicht über einen SQL Aufruf gefüllt habe... ;)

    Noch eine Frage.
    Du führst zwei mal eine Konvertierung durch.
    Warum genau machst du das?

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(TblKundenBindingSource.Current, DataRowView)
    2. lblWert.Text = rwKunde.Item(0)
    3. lblWert.Text = rwKunde.Item(1)
    4. lblWert.Text = rwKunde.Item(2)
    5. 'oder
    6. Dim rwKunde = TblKundenBindingSource.Current
    7. lblWert.Text = rwKunde.Item(0)
    8. lblWert.Text = rwKunde.Item(1)
    9. lblWert.Text = rwKunde.Item(2)


    Funktioniert ja auch.
    Aber ich gehe mal davon aus das die Konvertierungen einen Zweck erfüllen.

    stepper71 schrieb:

    Du führst zwei mal eine Konvertierung durch.
    Du ja auch, nur du merkst es nicht.

    machma Option Strict On! - dann siehst du es.

    Aber meine Casterei holt konkret die angewählte typisierte DataRow aus der BindingSource, während deine Casterei nur einen einzigen Spaltenwert dieser DataRow zutage fördert.
    Mein erster Cast ist wie deiner, der castet auf DataRowView. gugge DataRowView im ObjectBrowser, siehe Property Row As DataRow.
    Diese Row ist aber eine typsierte Row, nämlich eine KundeRow, und all deren Möglichkeiten gewinnt man, wenn man auch darauf castet. Gugge Proggen in typisierter Manier auf vier Views-Videos.
    Ich beginne zu erahnen was genau du damit meinst.

    Eine andere Frage noch:
    Ich bekomme nach der Auswahl eines Kunden in der combobox immer die Daten des zuvor angewählten Kunden angezeigt.
    Beispiel:
    Formular wird geöffnet. Es steht Müller in der combobox
    Ich wähle Meyer an, es werden die Daten von Müller ausgegeben.
    Ich wähle Schulze an, es werde die Daten von Meyer ausgegeben.
    etc....
    Kann es sein das ich das falsche Event bei der Combobox abfrage?
    D.h. die Änderung der Bindingsource findet erst nach diesem Event statt.

    Bisher sieht das wie folgt aus:

    VB.NET-Quellcode

    1. Private Sub cboKundenID_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboKundenID.SelectedIndexChanged
    2. 'Dim rwKunde = DirectCast(DirectCast(TblKundeBindingSource.Current, DataRowView).Row, KundeRow)
    3. Dim rwKunde = DirectCast(TblKundenBindingSource.Current, DataRowView)
    4. 'Dim rwkunde = TblKundenBindingSource.Current
    5. If rwkunde IsNot Nothing Then
    6. txtKundenNr.Text = DirectCast(rwkunde.Item(1), String)
    7. txtKundenName.Text = DirectCast(rwkunde.Item(2), String)
    8. lblWert.Text = CType(rwkunde.Item(0), String)
    9. lblwert2.Text = CType(cboKundenID.SelectedValue, String)
    10. End If
    11. End Sub


    Dabei liefert die BindingSource immer die Daten die zuvor angewählt waren, das Control liefert den aktuell ausgewählten Wert.
    ich bete es pausenlos immer wieder herunter: Lasst die Finger vonne Controls, trennt Oberfläche und Daten, wenns irgend geht.
    Möglichst immer am Dataset arbeiten, mit typisierten DataRows.
    Falls die aktuelle User-Sicht gefragt ist, sich an die BindingSource wenden - nicht an die Controls.
    Also nu guggemol die Events, die BindingSource dir bietet - ObjectBrowser kennste?




    wie gesagt - mit typisierten DataRows arbeiten - welchen Datentyp hat deine rwKunde?
    Wie kann man nur so penetrant recht haben..... ;)

    Habe mir die Ereignisse von der der BindingSource angeschaut (ObjectBrowser ist bekannt) und die scheinbar richtige gefunde, den es funktioniert jetzt! Vielen Dank!

    Code sieht jetzt wie folgt aus:

    VB.NET-Quellcode

    1. Private Sub TblKundenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles TblKundenBindingSource.CurrentChanged
    2. 'Dim rwKunde = DirectCast(DirectCast(TblKundeBindingSource.Current, DataRowView).Row, KundeRow)
    3. Dim rwKunde = DirectCast(TblKundenBindingSource.Current, DataRowView)
    4. 'Dim rwkunde = TblKundenBindingSource.Current
    5. If rwkunde IsNot Nothing Then
    6. txtKundenNr.Text = DirectCast(rwkunde.Item(1), String)
    7. txtKundenName.Text = DirectCast(rwkunde.Item(2), String)
    8. lblKundeID.Text = CType(rwkunde.Item(0), String)
    9. End If
    10. End Sub


    Welchen Datentyp hat "meine" rwKunde? Gute Frage.
    Ich würde sagen ein DataRowView Objekt? (Was eine Datenzeile aus der Tabelle darstellt, richtig?)

    Ich habe angefangen deine 4viewVideos durchzuarbeiten, tu mich aber noch sehr schwer damit.
    Wenn ich es als Laie erklären soll würde ich sagen: typisiert = festgelegte Auswahl, nicht typisiert = "ichtippeaufdieseSpalte" ....

    Wenn ich in obigen Beispiel meine ID haben möchte (Spalte0), habe ich also 2 Zeilen bis ich den Wert habe.
    Wäre es auch möglich den Wertemember (die ID) direkt abzurufen, also in der Art: TblKundenBindingSource.current.wert??
    DataRowView - sehr richtig! :thumbsup:

    DataRowView hat eine .Row-Property - As DataRow. Tatsächlich ist da sogar die typisierte KundenRow drinne - deshalb kann und sollte man diese Row-Property auf KundenRow casten, und dann siehts so aus:

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(DirectCast(TblKundeBindingSource.Current, DataRowView).Row, TblKundenRow)
    Möglicherweise musst du noch einen Import setzen - das schlägt dir Intellisense aber auch im SmartTag vor (ich hoffe, du weißt, wovon ich rede, ansonsten gugge Visual-Studio richtig nutzen, wie Intellisense Importe vorschlägt).
    vlt. heißt es auch nicht genau TblKundenRow, aber so ähnlich, je nachdem, wie du deine KundenTabelle benannt hast: Kunde, TblKunde, TblKunden, Kunden - und jeweils Row angehängt.

    Am Ende siehts so aus:

    VB.NET-Quellcode

    1. Private Sub TblKundenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles TblKundenBindingSource.CurrentChanged
    2. Dim rwKunde = DirectCast(DirectCast(TblKundeBindingSource.Current, DataRowView).Row, TblKundenRow)
    3. txtKundenNr.Text = rwKunde.KundenNr.Tostring
    4. txtKundenName.Text = rwKunde.Name
    5. lblKundeID.Text = rwKunde.ID.Tostring
    6. End Sub
    Was aber auch Quatsch ist, denn die Controls liessen sich viel einfacher direkt im Designer an die TblKundenBindingSource binden.
    Was wiederum in vier Views-Videos gezeigt ist :D

    stepper71 schrieb:

    ich zeige in einer Combobox die Daten einer Tabelle über eine Bindingsource an.
    Habe ich daqs richtig verstanden: Du nutzt eine ComboBox?
    Zum Anzeigen von Daten einer Tabelle würde ich ein DataGridView nehmen.
    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!
    @ErfinderDesRades
    Gefühlt würde ich sagen es schimmert ein Licht am Ende des Tunnels...

    Wenn ich es mit eigenen Worte formuliere:
    DataRowView ist ein Objekt welches eine DatenZeile aus meiner Tabelle darstellt, ansprechen würde ich die einzelnen Datenspalten mit dem Namen oder der Position der Spalte.
    Mit dem zweiten casten legts du jetzt das Schema der Tabelle (Welche Spalte ist vorhanden und wie heißt Sie) auf diese Datenzeile, damit steht die Information: Datenzeile.Spaltenname zur Verfügung.
    Ist das so annähernd richtig?

    Ich habe jetzt deinen Vorschlag übernommen, das sieht dann so aus:

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(DirectCast(TblKundenBindingSource.Current, DataRowView).Row, tblKundenRow)
    2. If rwKunde IsNot Nothing Then
    3. txtKundenNr.Text = rwKunde.KundenNr
    4. txtKundenName.Text = rwKunde.KundenName
    5. lblWert.Text = rwKunde.IDKunden.ToString
    6. End If


    Was wunderbar funktioniert!

    Danach habe ich deinen Ratschlag, die Controls direkt anzubinden ausprobiert
    Funktioniert sehr gut!!

    Womit eigentlich die gesamte Sub überflüssig wird.
    Somit sind alle Controls direkt an die bindingsource gebunden und die Ereignisprozdur zum aktualisieren der Felder ist überflüssig.
    (Worauf die mich/uns glaube ich die ganze Zeit immer hinweist, wenn ich das jetzt richtig verstanden habe..... ;-))

    Erstmal vielen Dank für die Nachhilfestunde!


    @RodFromGermany
    Das währe natürlich auch möglich. Es soll hier aber ganz klassisch mit wenig Platzverbrauch in einer Kombobox der Kunde gewählt werden, die anderen Daten dazu (Kundennr, etc) sollen an anderer Stelle im Formular angezeigt werden.

    stepper71 schrieb:

    an anderer Stelle im Formular angezeigt werden.
    OK, das ist eine Design-Frage.
    Du kannst natürlich einen Popup-Dialog anzeigen mit BorderStyle = None, damit wäre ggf. die Platzfrage anderweitig gelöst.
    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!
    @ErfinderDesRades:
    Ich habe ein Problem mit der Definition:

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(DirectCast(TblKundenBindingSource.Current, DataRowView).Row, tblKundenRow)


    Ich habe (schon öfters) mein Projekt auf einen anderen Rechner kopiert auf dem auch ein SQLServer läuft, die dort angelegt Datenbank heißt genauso wie auf meinem Rechner.
    Normalerweise passe ich dort nur den SQL Connectionstring an und alles funktioniert.
    Nach dem letzten mal hat dies erst auch funktioniert. Aber nach dem 3. Aufruf den Programm bekomme bei obiger Zeile immer den Fehler:

    "Objektverweis wurde nicht auf eine Objektinstanz festgelegt"

    Auf meinem Rechner funktioniert es nach wie vor ohne Fehlermeldung.
    Wenn ich diesen Fehler mit "Weiter" bestätige läuft das Programm auch ganz normal.
    Kannst du mir hiermit weiterhelfen?
    Wenn ich im Designer auf die BindingSource gehe und dort auf Datenvorschau bekomme ich alle Daten angezeigt, genauso beim Dataset.
    Dort sind auch keine Filter gesetzt.
    Wenn ich die Zeile in

    VB.NET-Quellcode

    1. dim rwKunde = DirectCast(TblKundenBindingSource.Current, DataRowView)


    ändere, kommt die Fehlermeldung nicht mehr.
    sorry.
    Die Fehlermeldung kommt dann nur nicht in der Zeile sonder später beim ersten Zugriff auf die Daten:

    ....= rwKunde.Item(0)

    Wenn ich mit dem Debugger mit die bindingSource.current angucke ist die tatsächlich nothing.
    Aber warum auf diesem Rechner und nicht auf einem anderen versteh ich nicht.

    Wie könnte ich dieses Nothing verhindern?
    was soll den rwKunde.Item(0) sein?
    Gibts da keine vernünftig bezeichnete Property? Ist doch ein typisiertes Dataset, oder?
    hast du Option Strict On!?


    Kannst mal Screenshot des Dataset-Designers posten, dann kann ich weissagen, wie bei dir die Properties und Methoden heißen, denn der Designer generiert nach einem einfachen Schema.
    Das typisierte Dataset habe ich ja nur wenn der "richtige" code durchläuft:

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(DirectCast(TblKundenBindingSource.Current, DataRowView).Row, tblKundenRow)


    aber dann kommt die Fehlermeldung.
    Also habe ich probiert:

    VB.NET-Quellcode

    1. Dim rwKunde = DirectCast(TblKundenBindingSource.Current, DataRowView)


    Dann kommt erst die Fehlermeldung beim Zugriff, den kann ich dann aber nur noch mit rwKunde.Item(0) machen.

    Das ganze scheint aber irgendwie ein Timingproblem zu sein.
    Dieser Code läuft ab wenn in den Controls etwas eingegeben wird, bzw. wenn ein Wert auf einer Combobox ausgewählt wird.
    Bei den Comboboxen haben ich NICHT das Ereigniss von der combobox genommen (wie von Dir empfohlen), sondern greife auf das Ereigniss CurrentChanged der bindingsource zu.
    Wenn beim Programmstart das Formular geladen wird, wird dieses Ereigniss auch ausgelöst durch das laden der Daten.
    (Was auf einem anderen Rechner aber kein Problem ist!)

    Wenn ich diese Ereignisse an der bindingsource weglasse, startet das Programm ohne Fehlermeldungen und funktioniert einwandfrei. (Ausser das das Ereigniss nicht mehr bei den comboboxen ausgelöst wird)

    Kann ich die Startreihenfolge irgenwie beeinflussen, so daß dieses Ereigniss beim laden des Formular erst etwas später stattfindet?

    Als Notlösung habe ich auch schon versucht das Ereigniss SelectedIndexChanged von der Combobox zu nehmen.
    Das reagiert aber, wie zuvor bebschrieben, immer um eine Auswahl versetzt.D.h. es wird immer der Wert geliefert den zuvor eingestellt hatte....