Richtige Datenbindung bei Modalem Form mit weiteren Unter-Tabellen

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

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

    Richtige Datenbindung bei Modalem Form mit weiteren Unter-Tabellen

    Guten Tag,

    ich hoffe ihr könnt mir wie letztes mal wieder auf die Sprünge helfen:
    Es geht um eine ganz einfache Kontakteverwaltung nach folgendem Schema: Es gibt eine Kontakte-Tabelle, welches die "Kern" Kontakte darstellt. Zu jedem Kontakt gibt es beliebig viele "Ansprechpartner" (sozusagen "Unter-Kontakte"). Außerdem gibt es die Tabelle Anreden in der die verschiedenen Anreden gespeichert sind (Herr / Frau / Firma / ...). Die Tabelle Anrede soll dabei für beide anderen Tabellen zur Verfügung stehen.
    Im Start-Form wird ein Datagridview mit dem Inhalt der TblKontakte angezeigt. Hier soll der Nutzer nur schauen können, also Readonly. Mit Doppelklick auf eine Zeile wird ein Modales Form geöffnet, in dem dann die Kontaktdetails im Detail-View geändert werden können. Das klappt auch super.
    Jetzt soll gleichzeitig in dem Form Kontaktdetails ein zusätzliches Datagridview angezeigt werden, in dem die Ansprechpartner für diesen Kontakt vermerkt sind. Diese sollen im Datagridview angezeigt und auch bearbeitet werden können.
    Das klappt leider nicht und ich komme nicht dahinter was ich falsch mache.

    Mein Quellcode:
    Form Kontakte (Hauptform)

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.IO
    3. Public Class FrmKontakte
    4. Dim _Datafile As New FileInfo("TdsKontakte.xml")
    5. Private Sub FrmKontakte_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. If _Datafile.Exists Then 'Falls das Dataset schon existiert wird es geladen
    7. TdsKontakte.ReadXml(_Datafile.FullName)
    8. Else 'Wenn es noch nicht existiert, werden die Anreden hinzugefügt
    9. Dim RwAnredeHerr = TdsKontakte.TblAnrede.AddTblAnredeRow("Herr")
    10. Dim RwAnredeFrau = TdsKontakte.TblAnrede.AddTblAnredeRow("Frau")
    11. TdsKontakte.TblAnrede.AddTblAnredeRow("Firma")
    12. 'Zu Testzwecken hier erstmal nur statische Datensätze...
    13. TdsKontakte.TblKontakte.AddTblKontakteRow(RwAnredeHerr, "Max", "Mustermann", "Musterstraße", "12345", "Musterstadt", "12345-2231", "Max@muster.de", "")
    14. TdsKontakte.TblKontakte.AddTblKontakteRow(RwAnredeFrau, "Maria", "Musterfrau", "Testweg", "54321", "Neustadt", "43321-31221", "Maria@test.de", "")
    15. End If
    16. End Sub
    17. Private Sub FrmKontakte_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    18. TdsKontakte.WriteXml(_Datafile.FullName)
    19. End Sub
    20. Private Sub TblKontakteDataGridView_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles TblKontakteDataGridView.CellDoubleClick
    21. Dim dialog As New FrmKontaktdetails(DirectCast(DirectCast(TblKontakteBindingSource.Current, DataRowView).Row, TdsKontakte.TblKontakteRow))
    22. dialog.TdsKontakte = Me.TdsKontakte
    23. dialog.ShowDialog()
    24. End Sub
    25. End Class


    (Die Möglichkeiten zum Hinzufügen und löschen von Datensätzen müssen hier natürlich noch implementiert werden...)



    Mein Modales Unterform:

    VB.NET-Quellcode

    1. Public Class FrmKontaktdetails
    2. Dim _RwKontakt As TdsKontakte.TblKontakteRow
    3. Public Sub New(ByRef RwKontakt As TdsKontakte.TblKontakteRow)
    4. ' Dieser Aufruf ist für den Designer erforderlich.
    5. InitializeComponent()
    6. ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
    7. TblKontakteBindingSource.DataSource = RwKontakt
    8. _RwKontakt = RwKontakt
    9. End Sub
    10. Private Sub FrmKontaktdetails_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    11. TblAnredeBindingSource.DataSource = TdsKontakte.TblAnrede
    12. 'Dashier ist jetzt mein letzter Verzweifelter Versuch gewesen. Hier muss dann wohl irgend etwas anderes hin:
    13. TblAnsprechpartnerBindingSource.DataSource = _RwKontakt.GetChildRows("FK_TblKontakte_TblAnsprechpartner")
    14. End Sub
    15. End Class



    Falls das hilft -> Ich habe die assembly mit angehangen.

    Danke!

    Grüße
    Philipp
    Bilder
    • Datenmodell.png

      17,44 kB, 523×449, 36 mal angesehen
    • FrmKontaktdetails.png

      15,56 kB, 829×454, 35 mal angesehen
    • FrmKontakte.png

      12,43 kB, 1.080×533, 38 mal angesehen
    Dateien
    • Kontakte.zip

      (243,5 kB, 33 mal heruntergeladen, zuletzt: )
    Also: Das Grundsatzproblem ist die formübergreifende Datenweitergabe.
    Erstmal ist scheinbar alles richtig gekoppelt. Das Problem ist aber, dass Du die DataSource im SubForm für TblKontakteBindingSource auf eine einzelne DataRow setzt. Das ist an sich zwar sinnvoll, führt aber dazu, dass die TblAnsprechpartnerBindingSource nicht mehr richtig funktioniert, da eingestellt ist, dass von der TblKontakteBindingSource der DataMember FK_TblKontakte_TblAnsprechpartner hergenommen werden soll - also die Ansprechpartner der Row. Eine einzelne, losgelöste Row hat aber diesen DataMember nicht mehr! Das funktioniert nur, solange die TblKontakteBindingSource auf eine DataTable verweist. Denn die hat Verbindung zu einer anderen DataTable. Die einzelne DataRow aber nicht. Daher klappt das alles nicht. und Du musst zu Deinem Verzweifelungsversuch greifen. Der ja funktioniert.
    Ich würde das aber durch tDS-Datenübergabe lösen. Denn die tDS-Daten sind nicht im SubForm vorhanden und deshalb musst Du bisher tricksen, um an Deine Daten zu kommen. Sobald Du aber alle Daten im SubForm hast, setzt Du einfach die TblAnsprechpartnerBindingSource auf die richtige Position* und fertig. Denn Du stellst ja keine Controls zur Verfügung, die die BS-Position verändern. Das führt somit dazu, dass Du immer bei dem Kontakt bleibst, den Du ausgewählt hast. Und das soll ja so sein/bleiben.

    Wie Du die tDS-Daten von A nach B bringst, bleibt Dir überlassen. Das einfache Zuweisen à la Dialog.TdsKontakte = Me.TdsKontakte reicht nicht, da die BindingSource dadurch icht beeinflusst wird. EdR hat seine Tricks, ich hab meine. Ich suche und verlinke …: seine und meine Vorgehensweise (einen Post später)

    * da verrat ich aber noch nicht, wie Du das machen könntest
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

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

    Geil, einfach nur Geil :thumbup:

    Es funktioniert, ich habe es auf die Art gelöst eine Zusätzliche Bindingsource einzufügen und diese dann auf das ursprungs-Dataset verweisen zu lassen.

    Die Übergabe der Bindingsource-Position fühlt sich so wie ich es gemacht habe etwas gemogelt an, bin mir nicht sicher ob das immer und sicher hinhaut, wenn man zum Beispiel einen neuen Datensatz einfügen will und direkt im Fenster öffnet. Wobei dann könnte man irgendwas richtung bindingsource.movelast unternehmen. Fühlt sich aber jetzt grade beim drüber nachdenken nicht wirklich richtig an.

    Hätte eigentlich eher an sowas gedacht wie ID aus der aktuellen row auslesen (directcast(directcast(....).row, ...).ID und diese dann übergeben. Da fehlt mir in der bindingsource dann aber die findbyID() Funktion für :whistling: :whistling:

    VB.NET-Quellcode

    1. Private Sub TblKontakteDataGridView_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles TblKontakteDataGridView.CellDoubleClick
    2. Dim frm As New FrmKontaktdetails()
    3. frm.BsTdsKontakte.DataSource = TdsKontakte
    4. frm.TblKontakteBindingSource.Position = TblKontakteBindingSource.Position
    5. frm.ShowDialog(Me)
    6. End Sub

    Philipp schrieb:

    dann aber die findbyID() Funktion
    kann man sich ja selber schreiben.
    Ist bei meine Tricks mit dabei, heisst BindingSource.MoveToRow(rw) - Extension.
    Sie orientiert sich nicht an einer ID, sondern an der DataRow selbst (die die Id ja enthält (und wenn sie keine Id enthält macht das so auch nix)).