DataGridView mit ComboBox Spalte die in jeder Zeile andere Einträge haben soll

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von OliverSte.

    DataGridView mit ComboBox Spalte die in jeder Zeile andere Einträge haben soll

    Moin moin,

    ich habe hier ein DGV mit zwei Combobox Spalten. In der ersten Spalte "Adresstyp" wähle ich den Adresstyp aus (Kunde, Lieferant, Hersteller, etc.). In der zweiten Spalte wähle ich eine Adresse, wobei mir der Name angezeigt, aber die ID im Dataset gespeichert wird (DisplayMember, ValueMember). Das DGV ist mit einer BindingSource ans Dataset gebunden, die Combobox in Spalte 2 hat eine eigene BindingSource an die Adressen. Die Combobox in Spalte 1 fülle ich manuell über .Items.Add(""). Dieses Setting funktioniert ganz prima.

    Nun sollen in der zweiten Spalte aber nur die Adressen angezeigt werden, die dem jeweiligen Typ entsprechen. Wähle ich "Kunde" nur die Kunden, bei "Hersteller" nur die Hersteller.
    Das geht ohne groß nachzudenken ganz einfach: Sobald ich den Typ ändere (CellLeave), setze ich einen Filter auf die BindingSource der Combobox in der zweiten Spalte. Soweit so gut.

    Nun stell dir mal vor, dass da schon ein Eintrag ist. Also ein "Kunde" mit "Kundenname" steht im DGV. In einem neuen Datensatz lege ich nun einen anderen Adresstyp fest, sagen wir "Hersteller". Das Ereignis CellLeave filtert wieder die BindingSource der zweiten Combobox und dann knallt es. Weil der Eintrag im ersten Datensatz nicht mehr zur neu gefilterten DataSource passt. Ja klar, ist ja ein anderer Adresstyp.

    Ich vermute, ich muss die BindingSource von der Combobox in Spalte 2 (nur der Zelle!) lösen, sobald der Datensatz gespeichert ist. Außerdem bei Änderung des Adresstyps den Wert in Spalte 2 zunächst löschen, bevor die BindingSource gefiltert wird (sonst knallt es). Da meine Umgebung noch eine Stufe komplexer ist, als hier beschrieben, ist das bestenfalls aufwändig, da man bei jedem Masterdatensatz das komplette DGV neu durchackern müsste. Das Form mit dem DGV enthält bei mir eine Adresse, die mit AdressID in der n:m Tabelle steht. damit wird das DGV zunächst gefiltert.

    Bevor ich also den feinsten Spaghetticode produziere und es am Ende doch nicht richtig rund läuft, dachte ich, ich frag mal. Das müsste doch schonmal jemand gemacht haben und zeigt mir, wie es geht. Welche Ereignisse zu benutzen sind und und was darin zu tun ist.

    Viele Grüße Oliver
    Bilder
    • Combobox in DGV.jpg

      27,3 kB, 525×208, 41 mal angesehen
    Moin allerseits,

    naja klar benutze ich ein typisiertes Dataset. Ohne das würde ich mich gar nicht trauen, hier eine Frage zu stellen ;)
    Ich habe mein Projekt einmal auf das Nötigste reduziert und mit allem Pipapo (zwei Helper-Dlls und Testdaten) hier angehängt. Sollte so kompilieren und laufen. Testdaten sind auch drin.
    Sollte jemand neue Adressen anlegen wollen, bitte zuerst den grünen Button drücken und dann die Felder ausfüllen und speichern!

    Als erstes wählt man die Adresse, der man Zusatzadressen zuweisen möchte. Sagen wir mal "Kunde 2, 2.".


    Auf dem Tab "Zusatzadressen" soll nun zunächst die Adresstyp gewählt werden, dann die passende Adresse.
    Wählen wir mal "Lieferant" aus.


    Dann sollen in der zweiten Combobox nur die Lieferanten stehen!
    Ich habe im Testprojekt den Filter mal auskommentiert, so sind da alle Adressen sichtbar.


    Mit der Tabelle Zusatzadressen realisiere ich so eine n:m Relation, bitte Details dazu direkt im Dataset Designer nachsehen.
    Wenn man im Tab "Adresse" einen Kunden anklickt, wird über CellClick die BindingSource des DGV Zusatzadressen gefiltert. Wüsste jetzt gar nicht, wie ich das anders machen sollte.

    C#-Quellcode

    1. ​bsZusatzadresse.FilterX("AdresseID = ?", rowKunde.ID);


    Bilder
    • Combobox in DGV 3 Zusatzadresse auswählen.jpg

      29,03 kB, 446×231, 264 mal angesehen
    • Combobox in DGV 2 Lieferanten auswählen.jpg

      21,69 kB, 417×188, 258 mal angesehen
    • Combobox in DGV 1 Kunde wählen.jpg

      90,9 kB, 1.188×872, 264 mal angesehen
    Dateien

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

    Hallo

    Ich hätte Dir einen Ansatz - ohne Gewähr:

    Füge doch eine Combobox inkl. neuem Bindung hinzu (neben dem Datagrid). - Das Datagrid wird nur noch verwendet zum Anzegen, Datensätze werden dann auserhalb gepflegt.
    Bei Datenquellen - Weitere Datenquellen - Projektdatenquellen - TermineDTS - Adressen
    Member anzeigen - Kunde
    Wertemember - ID
    Ausgwählter Wert: bsZusatzadresse - ZusatzadresseID

    Danach könntest Du ja die neue AdressBindingSource1 entsprechend filtern - leider kann ich Dir da nicht weiterhelfen - ich kann nur etwas vb.net..

    Hoffe es klappt
    Moin Panter,
    das ist ein guter Ansatz, Danke für den Denkanstoß.
    Es ist wohl so, dass man eine BindingSource für ComboBoxen nur über die gesamte Spalte definieren kann. Oder anders, jede Zeile enthält die selbe (!) BindingSource. Man kann die Source gar nicht pro Zelle, sondern nur für die Spalte ändern.
    Ich habe mit einer weiteren ungebundenen Spalte experimentiert, die nur zur Auswahl der Adresse die entsprechend gefilterte BindingSource bekommt und dann die gebundene Spalte mit ZusatzadresseID und eine weitere ungebundene mit dem Kundennamen (zur Anzeige) füllt. Die vielen CellClick/CellLeave Ereignisse, die man dann benutzen müsste, das führt zu dem o.g. Spaghetticode, den ich vermeiden möchte.
    Also noch mal danke, ich probier da mal was mit einer separaten ComboBox auf der Form neben dem DGV.

    Viele Grüße Oliver
    Hallo Oliver

    Ich habe dir noch eine 2. Ansatz:

    Verwende doch das CurrentCellChanged Ereignis. Filter setzen wenn du in der Spalte ZusatzadresseID bist, falls du nicht in der Spalte bist, entferne den Filter.

    Dann würde doch kurzfristig bei den anderen Zeilen die Adresse nicht mehr angezeigt, aber sobald der der Datensatz geändert ist, zeigt es die Adressen wieder an.

    LG Panter
    Ich habe keine Lösung beizusteuern (achja - vlt. doch!), aber ich finde, du hast das Problem hervorragend erklärt! :thumbup:
    Das ermöglicht, dassich dir leider gleich sagen kann: Das ist von Haus aus so nicht vorgesehen für die DGV-ComboboxColumn.
    Databinding sieht vor, dass die Combobox-Datenquelle alle Werte enthält, die auch tatsächlich in der Tabellenspalte vorkommen.
    Weil die DGV-Zelle (während die Combobox geschlossen ist) zeigt ja tatsächlich Ersatzwerte der richtigen Werte der DataTable an.
    Also wenn in einer FK-Spalte, die auf ZusatzAddressen verweist, der Wert 5 steht, sucht die Zelle in der ComboSource den Wert 5, um die Textdarstellung dazu anzeigen zu können.
    Wenn du der ComboSource nun den Wert 5 wegfilterst, in der Tabelle aber tatsächlich ein Datensatz diesen FK-Wert hat, dann ist natürlich Exception.

    Aber guckma - hier habichmich mit sowas ähnlichem herumgeärgert: Combobox-Auswahl einschränken

    Der Hack ist eben, dass bei der ComboBox das Databinding abgehängt wird, und was anneres eingefüllt.
    Das könnte man vlt. umfrickeln, dasses auch deine Anforderung erfüllt.
    Ich habe jetzt einfach mal zwei ComboBoxen über das DGV gesetzt, nur um Typ und Adresse zu bestimmen. Damit wird dann einfach ein Datensatz erzeugt und im DGV angezeigt. Soweit so schön, aber ich möcht ja gern das berechnete Feld "Kunde" aus "Adresse", statt der ID im DGV sehen, was mit einer ComboBox problemlos möglich ist (DisplyMember/ValueMember). Eine Textbox kann aber ja nur Columns der dem DGV zugrundeliegenden BindingSource anzeigen. Und in der n:m Tabelle gibt's nur IDs. Hmm, wat nu?

    Guck ich mir also jetzt mal das Gefriemel von @ErfinderDesRades an. Da binnich gespannt.
    Dateien
    So, ich melde mal Vollzug.
    Der Tipp von @ErfinderDesRades hat es mal wieder gebracht.
    Ich musste ne Weile herumdoktorn, bis ich das an meine Bedürfnisse angepasst hatte, da ich mich mit Linq und sowas nicht so gut auskenne und alles lange googeln muss, bis es dann funktioniert. Aber jetzt ist es easy und schön fluffig geworden.
    Nebenbei habe ich gemerkt, dass ich die bsZusatzdaten und bsZusatzadressen ja doch an die bsAdressen binden muss, damit die automatisch gefiltert werden. Das hatte @trix0 in seiner ersten Antwort wohl gemeint. Dadurch wird das ganze noch übersichtlicher, da keine IDs im DGV stehen und auch keine Defaultwerte reingeschrieben werden müssen.
    Allen Helfenden recht schönen Dank!

    Viele Grüße Oliver
    Dateien