Datagridview als mehrspaltige Combobox Problem mit Databinding

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

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Schoofi.

    Datagridview als mehrspaltige Combobox Problem mit Databinding

    Ich möchte ein Datagridview nutzen um eine mehrspaltige Combobox zu simulieren.
    Er soll den Wert aus der übergeordneten Tabelle in der eingeblendeten Zeile anzeigen und bei Click auf den Cellbutton das Datagridview einblenden um darin zu suchen.
    Das funktioniert wenn ich es mit Databinding machen will, aber nur wenn eine an das entsprechende Feld, hier ID_Apl gebundene Combobox vorhanden ist.
    Fehlt diese, klappt das nicht.
    Die Bindungen sind im Designer gesetzt.
    Woran kann das liegen? Muß ich eine Combobox versteckt auf dem Formular unterbringen oder geht das eleganter ?

    VB.NET-Quellcode

    1. Private Sub bsTbl_Nutzer_CurrentChanged(sender As Object, e As EventArgs) Handles bsTbl_Nutzer.CurrentChanged
    2. dtrowNutzer = DirectCast(DirectCast(Me.bsTbl_Nutzer.Current, DataRowView).Row, dsRechnerliste_be.tbl_NutzerRow)
    3. If Not Me.dgvApl.CurrentRow Is Nothing Then
    4. Me.dgvApl.FirstDisplayedScrollingRowIndex = Me.dgvApl.CurrentRow.Index
    5. End If
    6. End Sub
    7. Private Sub dgvApl_CellContentClick_1(sender As Object, e As DataGridViewCellEventArgs)
    8. Select Case e.ColumnIndex
    9. Case btnDown.Index
    10. If Me.dgvApl.RowCount > 9 Then
    11. Me.dgvApl.Height = CInt(intHoehe / 2 * 10)
    12. Else
    13. Me.dgvApl.Height = CInt(intHoehe / 2) * Me.dgvApl.RowCount
    14. End If
    15. Me.dgvApl.ScrollBars = ScrollBars.Vertical
    16. Me.dgvApl.Columns(e.ColumnIndex).Visible = False
    17. Case Else
    18. Me.dgvApl.ScrollBars = ScrollBars.None
    19. Me.dgvApl.Height = intHoehe
    20. Me.dgvApl.Columns(btnDown.Index).Visible = True
    21. Me.dgvApl.FirstDisplayedScrollingRowIndex = Me.dgvApl.CurrentCell.RowIndex
    22. End Select
    23. End Sub
    Ich habe neben zig anderen Tabellen eine Tabelle Nutzer und eine Tabelle Arbeitsplatz.
    In der Tabelle Arbeitsplatz ist die ID_Apl der Primärschlüssel, selbiger ist in der Tabelle Nutzer als Verweis enthalten.



    Ich möchte im Formular Nutzer den Arbeitsplatz auswählen lassen und Zusatzinfos, wie den Nutzer der aktuell dort sitzt mit anzeigen.
    Da es keine mehrspaltigen Comboboxen gibt, habe ich mir gedacht nutze ich ein Datagridview.
    Dieses enthält in jeder Zeile einen Button und sobald auf diesen geklickt wird, vergrößert sich das Datagridview um die Auswahl zu ermöglichen, beim Auswählen wird dann nur die ausgewählte Zeile angezeigt.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub bsTbl_Nutzer_CurrentChanged(sender As Object, e As EventArgs) Handles bsTbl_Nutzer.CurrentChanged
    2. dtrowNutzer = DirectCast(DirectCast(Me.bsTbl_Nutzer.Current, DataRowView).Row, dsRechnerliste_be.tbl_NutzerRow)
    3. If Not Me.dgvApl.CurrentRow Is Nothing Then
    4. Me.dgvApl.FirstDisplayedScrollingRowIndex = Me.dgvApl.CurrentRow.Index
    5. End If
    6. End Sub
    7. Private Sub dgvApl_CellContentClick_1(sender As Object, e As DataGridViewCellEventArgs)
    8. Select Case e.ColumnIndex
    9. Case btnDown.Index
    10. If Me.dgvApl.RowCount > 9 Then
    11. Me.dgvApl.Height = CInt(intHoehe / 2 * 10)
    12. Else
    13. Me.dgvApl.Height = CInt(intHoehe / 2) * Me.dgvApl.RowCount
    14. End If
    15. Me.dgvApl.ScrollBars = ScrollBars.Vertical
    16. Me.dgvApl.Columns(e.ColumnIndex).Visible = False
    17. Case Else
    18. Me.dgvApl.ScrollBars = ScrollBars.None
    19. Me.dgvApl.Height = intHoehe
    20. Me.dgvApl.Columns(btnDown.Index).Visible = True
    21. Me.dgvApl.FirstDisplayedScrollingRowIndex = Me.dgvApl.CurrentCell.RowIndex
    22. End Select
    23. End Sub



    Das funktioniert auch soweit.
    Nur das Databinding zwischen Formular und Datagridview funktioniert eigenartigerweise nur dann, wenn eine sichtbare Hilfscombobox auf dem Formular installiert ist.

    Datasource=bsRechnerliste_be
    Datamember=tbl_Arbeitsplatz
    Displaymember=Arbeitsplatz


    Die Datenbindung für das Datagridview sieht folgendermaßen aus

    Spoiler anzeigen

    Datasource=bsRechnerliste_be
    Datamember=tbl_Arbeitsplatz




    Das Formular sieht im entscheidenden Teil so aus

    Spoiler anzeigen



    Die Spalte V enthält den btndown um das Comboboxverhalten zu simulieren.



    Mit der Hilfscombobox verhält sich das Datagridview wie erwartet, ohne steht es standardmäßig auf dem ersten Datensatz.

    kleines Demoprojekt

    Ich habe mal eine kleine Demo mit den wesentlichsten Programmbestandteilen gebastelt.
    Wenn Du die Bindungen in der Combobox außer Betrieb nimmst, siehst Du den Effekt.

    vb-paradise.de/index.php/Attachment/38814-Nutzer-zip/
    Dateien
    • Nutzer.zip

      (2,5 MB, 301 mal heruntergeladen, zuletzt: )
    Sorry, da hatte ich den falschen Ordner gepackt. Dadurch hatte er mein großes Originaldataset versucht zu laden, obwohl ich den Rest des Projektes schon abgespeckt hatte.
    Das ich Strict off auf on nach Neuanlegen des Projektes erst umstellen muß war mir auch noch nicht aufgefallen.
    Hier ist nun die richtige.Verzeichnis : d:\Nutzer

    vb-paradise.de/index.php/Attachment/38817-Nutzer-zip/
    Dateien
    • Nutzer.zip

      (486,07 kB, 252 mal heruntergeladen, zuletzt: )
    So wie ich das jetzt verstehe, möchtest du mit der ButtonColumn den DropdownButton einer Combobox simulieren...
    Da habe ich im Netz folgendes , glaube von @ErfinderDesRades, dazu gefunden - schaue dir das einmal an...
    Es gibt auch eine zweite einfachere Möglichkeit:
    Wenn du mehrere Spalten nur zum Suchen brauchst, dass du in der Tabelle tbl_Arbeitsplatz eine berechnete Spalte einfügst...
    z.B.: eine Spalte AusgabeAlles, wo die Expression-Eigenschaft diesen Ausdruck inne hat Convert(ID_Apl, 'System.String') + ' | ' + Arbeitsplatz
    In der Combobox dann diese zur Ansicht bringst und das DGV für solches wegläßt...


    Das ich Strict off auf on nach Neuanlegen des Projektes erst umstellen muß war mir auch noch nicht aufgefallen.

    Bilder
    • OptionStrictOn.PNG

      52,31 kB, 759×443, 247 mal angesehen

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

    Danke, die Grundeinstellung (Strict on) muß wohl bei der Neuiinstallation von Studio krachen gegangen sein, habe ich inzwischen korrigiert.

    Die Funktionalität, ist die die Du meinst, allerdings wollte ich es mit Databinding versuchen, In dem genannten Link muß ich die Combobox allerdings manuell füllen.
    Schade das es Microsoft bisher nur in ACCESS geschafft hat die Combobox mehrspaltig zu gestalten.
    Andererseits würde ich auch das merkwürdige Verhalten, das es nur mit Hilfscombobox funktioniert verstehen.

    Schoofi schrieb:

    Ich möchte im Formular Nutzer den Arbeitsplatz auswählen lassen und Zusatzinfos, wie den Nutzer der aktuell dort sitzt mit anzeigen.
    Das ist ein klassischer DetailView - und ich verstehe nicht recht, was du mit der mehrspaltigen Combobox vorhast. Außer, du willst in der Combobox mehrere Infos des Arbeitsplatzes bei der Suche haben.
    Andererseits würde ich auch das merkwürdige Verhalten, das es nur mit Hilfscombobox funktioniert verstehen.
    Deine Umsetzung ist einfach vermurkst...
    Da habe ich dir oben schon einen Vorschlag mit der berechneten Spalte gegeben - die müsste eigentlich genügen...
    Im Anhang findest du eine abgeänderte Version deiner Testsolution zum anschauen - da kannst du per Arbeitsplatz mehrere Nutzer angeben, dass ist mit deinem Datenmodel so vorgegeben...
    Dateien
    • Nutzer00.zip

      (47,62 kB, 378 mal heruntergeladen, zuletzt: )

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

    Danke für Deine Bemühungen,allerdings habe ich die Aufgabenstellung wahrscheinlich nicht klar genug definiert.

    Ich möchte Nutzer nach Namen suchen bzw. neu anlegen.
    Diese werden dann mit der Combobox einem Arbeitsplatz zugewiesen bzw. bei Umzügen wird der Arbeitsplatz verändert.
    Das Namensfeld in der Combobox ist nur als Hilfestellung gedacht, das ich bei Platztausch schnell den richtigen Platz finde und auch keine MA staple.
    Den Trick mit der berechneten Spalte wende schon an, allerdings habe ich dann keinen festen Spaltenaufbau, sondern flattrige Spaltenbegrenzer, es sei denn es gäbe eine Lösung auch dort die Tabs unterzubringen.

    Deine Lösung ist praktisch, wenn ich wissen möchte wer alles auf welchem Arbeitsplatz sitzt.

    Schoofi schrieb:

    Ich möchte Nutzer nach Namen suchen bzw. neu anlegen.
    Diese werden dann mit der Combobox einem Arbeitsplatz zugewiesen bzw. bei Umzügen wird der Arbeitsplatz verändert
    Das ging bei deinen Vorposts aber nicht klar heraus...
    Das bedeutet nur eine kleine Änderung meines obigen Vorschlages.
    Dateien
    • Nutzer01.zip

      (47,77 kB, 284 mal heruntergeladen, zuletzt: )
    Die Combobox, die sich nun im Datagrid befindet wollte ich in der Detailansicht des Formulars abbilden.
    Die sollte dort mehrspaltig sein um den aktuell auf dem Platz sitzenden MA zusätzlich mit anzuzeigen.
    Ich bekomme z.B. die Info, das z.B. ein Herr Müller in den Raum 3D-030 auf den Platz von Herrn Meier zieht.
    Herr Meier zieht dann woanders hin oder der MA soll in den Raum 5D 070 gegenüber von Frau Schulz.
    Die Zahlen die in der Tabelle Arbeitsplatz hinter der Raumnr stehen sind übrigens die genauen Positionen innerhalb des Raums.

    Das was in der Besispieltabelle mit 3 Datensätzen relativ simpel aussieht, wird bei 170 Nutzern und rund 200 Arbeitsplätzen, rasch unübersichtlich, deshalb brauche ich beide Infos in der Combobox.

    Deshalb der Versuch das Datagridview umzufunktionieren.

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

    Es scheint, dass dein Datenmodel nicht diese Voraussetzungen erfüllt, weil es dich dann auf eine mehrspaltige Combobox zurückgreifen lässt...
    Ich habe mir einmal so eine Arbeitsplatzzuordnung aus meiner Sicht erstellt. Schaue einmal, ob du da etwas gebrauchen kannst, dass dich ev. zu deinem Ziel führt.
    Ist halt eine andere Sichtweise und ist DatasetOnly-gestaltet...
    Dateien
    • Nutzer03.zip

      (24,76 kB, 271 mal heruntergeladen, zuletzt: )
    Danke für Deine Mühe.
    Ich habe mir die Lösung mal angesehen.
    Für eine Raumverwatung ist Deine Lösung ideal, leider nicht für meinen Anwendungsfall.
    Bi mir muß Zuweisung innerhalb des Detail-Formulars Nutzer erfolgen. Dieses ist insgesamt schon ziemlich voll, so das ich da nur eine Zeile für den Arbeitsplatz zur Verfügung habe.
    Ich möchte aber wenn ich einen Nutzer dazubekomme, aber auch sofort alles was zu Ihm gehört auf dem Formular einpflegen und nicht noch in eine Raumverwaltung wechseln.

    Bei dem eigentlichen Problem mit der Datenbindung sieht es so aus, das scheinbar die ID_Apl aus der Bindingsource Nutzer durch das Datagridview nicht an die Bindingsource Arbeitsplatz weitergegeben wird.
    Die Combobox scheint da als Brücke zu funktionieren. Wenn die Bindungsource auf der richtigen Position steht, zeigt auch das Datagridview die richtige Positon an.
    Warum die Brücke bei unsichtbarer Bindingsource nicht funktioniert ist mir rätselhaft.
    Interessant wäre auch zu wissen wie ich die ID an die Bindungsource direkt binden kann.
    Nur auf die Ereignisse zu reagieren ist mir zu unsicher, falls ich was übersehe.
    Ich versteh einiges nicht, was du sagst - wie "unsichtbare BindingSource" - sind BindingSources denn jemals sichtbar?
    Oder was du dir unter "ID direkt an BindingSource binden" vorstellst.

    "Combobox-Brücke im Gegensatz zu DGV" - da klingelt immerhin etwas bei mir, nämlich dass ich die Beobachtung gemacht hab, dass man mit einer Combo den ausgewählten Wert mittels Databinding in eine andere BindingSource schreiben kann.
    So etwas kann Dgv nicht, und der Grund ist, dass Dgv keine bindebare SelectedValue-Property hat.
    Wenn ich recht überlege, finde ich das schade, und wäre eiglich eine hübsche Aufgabe, DatagridView zu beerben, und halt genau diese Property nachzurüsten.

    Vielleicht auch nicht - also ich zumindest hab mal was gebastelt, womit man BindingSources untereinander verknüpfen kann - egal ob und welche Controls angebunden sind. Damit kann ich dann auch sowas erreichen, dass die Auswahl in einem DGV in eine andere BindingSource geschrieben wird und viceversa - genau wie bei Combo- und List-boxen.

    Aber meine "BindingSourceBinder" - Klasse ist ziemlich kompliziert vom Code her - ja, und letztlich läufts auch über Events - aber das ist bei Databinding nicht anners.
    Die unsichtbare Bindingsource war ein Schreibfehler, das sollte eigentich eine unsichtbare Combobox sein. Solange die Combobox visible=true gesetzt ist funzt es, ist visible=false geht es nicht mehr.
    Unter ID direkt an Bindingsource binden, meine ich das durchreichen (vmtl das gleiche was Du mit schreiben meinst), also quasi das die Bindungsource die Info bekommt auf welche row sie zeigen soll.

    Die Idee die ID direkt von einer Bindingsource zur anderen durchzureichen hatte ich auch schon, aber dazu fehlen mir die Kenntnisse.
    Ich hatte auch schon überlegt auf die Änderung des datagridview Tag zu reagieren und dann die zu selectiertende row zu ermitteln, aber auch das habe ich nicht hinbekommen und birgt die Gefahr das ich was übersehe.

    Am liebsten würde ich die fertige Datagridview-Combobox als eigenes Steuerelement definieren und über den Designer anbinden, auch da muß ich noch rausbekommen wie es geht.
    Da ich das fertige Programm mit nur wenigen Admins nutze, werde ich bis ich eine andere Lösung habe die Combobox als Brücke drinlassen.

    Würde es aber trotzdem gern anders lösen und die Hintergründe verstehen.