DataBinding - Resynchronisation mit DGV erzwingen

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

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    DataBinding - Resynchronisation mit DGV erzwingen

    Hi,

    ich habe ein Problem, das vielleicht ein bissl komplex ist. Mal sehen, ob ich mein Anliegen verständlich machen kann.

    Ich habe eine Form mit zwei Datagridviews. In der ersten DGV werden Subdirectories aufgelistet. Wenn ich in dieser Liste ein Subdirectory auswähle, werden die darin enthaltenen Files in der zweiten DGV angezeigt.

    Befüllt werden beide DGVs über DataBinding aus einem typisierten Dataset. Wenn ich nun Subdirectories bzw. Files hinzufüge, umbenenne oder lösche dann notiere ich das im typisierten Dataset und damit werden die Änderungen in die beiden DGVs reflektiert.

    Soweit so gut!

    Nun kann ich von meiner Form ZWEI Instanzen öffnen. Wenn ich verschiedene Verzeichnisbäume anzeige, dann gibt es keine Kollisionen.

    Ich kann aber auch die gleiche Liste von Subdirectories anzeigen. Je nach ausgewähltem Subdirectories kann dann die Liste der Files übereinstimmen oder auch nicht. Die Sortierreihenfolge in den einzelnen Listen kann voneinander abweichen.

    Wenn ich nun in der einen Form etwa ein Subdirectory oder einen File umbenenne, dann soll diese Änderung auch in der anderen Form wirksam werden. Alles andere also die aktuelle Auswahl oder die Sortierreihenfolge sollen unverändert bleiben.

    Offensichtlich kann man die Datasources also nicht so einfach "zusammenstöpseln".

    Ich hab die Aktualisierung programmtechnisch gelöst ... aber es gibt ein Problem:

    Wenn ich in der FormA die Datasource aktualisieren, dann werden auch die DGVs der FormA geändert. In der FormB passiert natürlich erst mal nix. Deshalb stoße ich die gleiche Aktualisierung in der FormB an ... die läuft auch problemlos! Nur die DGVs werden nun nicht aktualisiert, weil sich ja in der DataSource keine Daten geändert haben, denn das wurde schon zuvor in der FormA erledigt.

    Kann ich irgendwie erzwingen, dass die DGVs in der FormB aktualisiert werden ?

    Meine Versuche bisher hatten keinen Erfolg:

    Quellcode

    1. alternateForm.SubdirListBindingSource.ResetBindings(metadataChanged:=True)
    2. alternateForm.SubdirListBindingSource.ResumeBinding()


    LG
    Peter

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

    @Peter329 Probier mal dies:

    VB.NET-Quellcode

    1. xx.DataSource = Nothing
    2. xx.DataSource = TABELLE
    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!
    form-übergreifendes Databinding.
    Hab ich dir noch nie davon erzählt?

    In einer Anwendung darf nur ein einziges Dataset benutzt werden.
    Leider generiert der form-Designer die Form-Klassen so, dass jedes Form sein eigenes Dataset erhält, das macht bei 2 Forms 2 Datasetse, und bei 5 Forms 5.
    Und da muss man umständliche Vorkehrungen zur Laufzeit treffen, um diese multiplen Datasetse zuverlässig zu vernichten bis auf eines, und alle Bindingsouces aller Forms immer auf dieses eine umstöpseln.

    Aber hat man das erst geschafft, ist das Problem verschwunden.
    Hi, erst mal recht herzlichen Dank, dass ihr euch mit meinem Problem befasst habt.

    @RFG
    Dein Vorschlag kling vernünftig - so hab ich das umgesetzt:

    VB.NET-Quellcode

    1. FileListBindingSource.DataSource = Nothing
    2. FileListBindingSource.DataSource = Me.DataSet1


    Aber schon die erste Anweisung scheitert:

    Argument Exception: Sort string contains a property that is not in the IBindingList.

    Ich sollte dazu vielleicht anmerken, dass ich die Sort Eigenschaft zuvor vom Program aus gesetzt habe, weil alle Listen beim Laden nach dem Namen aufsteigend sortiert werden.

    @EDR

    Natürlich hast du mir vom "formübergreifenden Databinding" erzählt. Ich sauge deine Ratschläge ja förmlich auf und deshalb habe ich die Sache mit dem "Umstöpseln" explizit in meinem Posting erwähnt.

    VB.NET-Quellcode

    1. Dim FormB = New Form1 'Assign base name
    2. alternateForm = FormB 'Assign alternate name in primary window
    3. FormB.FileListBindingSource.DataSource = Me.DataSet1 'Combine source
    4. FormB.Show() 'Display secondary window


    Solange FormA und FormB die gleiche Subdirectory Liste verwenden ist das ja auch alles in Ordnung.

    Aber wenn ich in der FormA ein anderes Subdirectory auswähle, dann wird die File Liste nicht nur FormA geändert (was vollkommen richtig ist), sondern auch in FormB (und das darf nicht sein !)

    Wenn ich der FormB ein anderes Subdirectory auswähle, dann bleibt die File List in FormB erhalten (was falsch ist) und die File Liste in FormA wird geändert (was ebenfalls falsch ist).

    Ich weiß, das ist alles nicht so ganz einfach nachzuvollziehen. Na, aber ihr seid ja Experten ... ich bin auf eure Kommentare gespannt!

    LG
    Peter

    Peter329 schrieb:

    is not in the IBindingList
    Da musst Du natürlich die richtigen Daten nehmen.
    Bei mir ohne DataSet, nur mit einer einfachen DataTable, läuft das so.
    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!
    Hmm ... na, da will ich mal versuchen ein paar Information zu geben, die sachdienlich sein könnten.

    btw zeile#2 - was soll die bewirken?


    Ganz einfach:

    In FormA verweist alternateForm auf FormB
    In FormB verweist alternateForm auf FormA

    So kann ich in meinem Coding mit alternateForm auf die jeweils "andere Form" verweisen.

    Und die ersten 3 deiner 4 Kommentare machen unrichtige Aussagen.


    Na gut ... meine Kommentare sind halt mit der heißen Nadel gestrickt. Sag mir halt, wie die richtig lauten sollten ... aber verbeißen wir uns nicht an Nebenkriegsschauplätzen.

    am gezeigten Code kanns nicht liegen, also läuft iwo anners was schief.


    Bist du da ganz sicher, dass die Sache mit dem "Umstöpseln" wirklich so funktioniert? Ich habe jetzt einige Tage an dieser Routine zugebracht.

    Es ist nur das folgende Event relevant:

    Event dgvSubdirectories.SelectionChanged: sobald das ausgewählte Subdirectory wechselt, wird die dgvFiles neu aufgebaut.

    Mehr isses nich! Ich trace alle Events ... und es tritt sonst nix anderes auf !

    Und zusammen mit dem "Umstöpseln" ergeben sich damit die o.a. Effekte bei der formübergreifenden Kommunikation!

    Any bright ideas?

    [edit]

    Und je länger ich darüber nachdenke, desto mehr scheint mir das auch plausibel:

    In FormA habe ich Subdir1 ausgewählt. Es wird die FileList1 angezeigt.

    Jetzt ändere ich in FormA die Auswahl auf Subdir2 ... und damit wird FileList2 angezeigt. Und wegen der Umstöpselei wird diese FileListe2 jetzt auch nach FormB übernommen. Ungeachtet dessen, welche Subdir in FormB ausgewählt ist! Und das ist schlicht und ergreifend falsch !

    Ich hab's ja schon gesagt, die Sache ist ein bissl komplex!

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Peter329“ ()

    Sag mir halt, wie die richtig lauten sollten
    Löschen - alle 4 - weil der 4 Kommentar lügt den Leser zwar nicht an, ist aber doch völlig üflüssig - dass FormB angezeigt wird steht ja im Code - dazu muss man keinen Kommentar lesen.

    Ansonsten mal das Event abhängen, und ausprobieren - iwo dran wirds ja liegen.

    Ansonsten mal ein Testprojekt anhängen, was lauffähig ist, und den Fehler reproduziert.
    Na ok, das dachte ich mir schon, dass man bei diesem Problem ohne ein lauffähiges Sample nicht weiter kommt. Ich werde also mal versuchen den Fehler in einem minimalistischem Projekt nachzustellen ... iss halt ein bissl Arbeit ... aber sollte machbar sein.

    Ein wenig Geduld ... ich melde mich bald zurück! :)
    so, da bin ich wieder, das ging ja doch flotter als erwartet.

    das heisst, das mit dem Event abhängen hast du probiert, oder ignoriert?


    Also, ich hab so viele Versuche gemacht, dass ich selbst nicht mehr weiß, was ich alles probiert habe. :)

    Hier ist nun eine Demo des beschriebenen Effekts im Anhang.

    Wenn man das Ding startet, erscheint FormA.

    In dieser Form, kann man mit Click Subdirectories auswählen. Dann wird die zugehörige File Liste angezeigt. Wenn das Subdirectory nicht zugreifbar ist, steht davor ein "?" ... in diesem Fall wird die dgvFiles "grau".

    Ein "+" vor dem Subdirectory, zeigt an, dass das Subdirectory weitere Unterverzeichnisse enthält. Durch Doppelclick auf das Subdirectory kann man sich eine Ebene tiefer hangeln.

    Zurück geht es mit dem "Up" Button.

    Außerdem funktioniert der Sort durch Click auf die Column Header.

    Das ist alles problemlos. Damit kann man sehr schön "spielen".

    Wenn ihr euch davon überzeugt habt, dann öffnet mit einem Click auf den "Window" Button ein ZWEITES Fenster, die FormB. Und das sollte zunächst mal UNABHÄNGIG von der FormA sein. Isses aber nich ! Wenn ich etwa in der FormA FileListen öffne, dann erscheinen die auch in der FormB, obwohl sich die Directory Auswahl in der FormB nicht geändert hat! Und in der FormB kann ich Verzeichnisse auswählen wie ich will, die dazu gehörigen FileListen werden einfach nicht angezeigt.

    Und das ist mein erstes Problem!

    Na, viel Spaß beim Ausprobieren! Ich hoffe, dass ihr mir helfen könnt! An dieser Kiste sitze ich jetzt schon einige Tage ... Vielleicht fehlt mir ja noch irgendwas Zentrales im Verständnis des DataBinding.

    LG
    Peter
    Dateien
    • DemoSample.zip

      (177,56 kB, 103 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Peter329“ ()

    ebbes sehr komisches

    VB.NET-Quellcode

    1. Module Module1
    2. Public intWindow As Integer = 0 'intWindow = 0 - no alternate window / intWindow = 1 - alternate window open
    3. Public FormA As Form1
    4. Public FormB As Form1
    5. End Module
    Da treiben die SeitenEffekte ja Seitensprünge und rauf und runter wie das Assyrische Imperium.

    Nu guck noch den hier:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    2. lblMessage.Text = ""
    3. If intWindow = 0 Then 'Load primary window
    4. Me.Text = "FormA"
    5. FormA = Me
    6. Else 'Load alternate window
    7. Me.Text = "FormB"
    8. FormB = New Form1
    9. alternateForm = FormA
    10. End If
    11. '...
    Also wenn du son Form startest, trägt es sich als FormA ein, und wenn du ein 2. Form davon startest, trägt sich dieses auch als FormA ein.

    Und im Click gibts dann diesen:

    VB.NET-Quellcode

    1. Private Sub cmdWindow_Click(sender As System.Object, e As System.EventArgs) Handles cmdWindow.Click
    2. myDebug("*** cmdWindow ***", "Y"c)
    3. If intWindow = 0 Then
    4. 'Open alternate window
    5. intWindow = 1
    6. Dim FormB = New Form1 'Assign base name
    7. alternateForm = FormB 'Assign alternate name in primary window
    8. FormB.FileListBindingSource.DataSource = Me.DataSet1 'Combine source ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    9. FormB.Show() 'Display secondary window
    10. Else
    11. lblMessage.Text = "Alternate window already open."
    12. End If
    13. End Sub

    Also ich blicke da nicht durch, welches Form da nun FormA und FormB sein wird, und was das für Konsequenzen hat.
    Alles was ich weiß ist, dass keiner der Kommentare eine richtige und nützliche Aussage macht.
    (Und das bei dieser ausserordentlich verzwickt gebauten Architektur)

    Ich schmeisses mal raus, und gucken, obs dann wieder ordentlich geht.

    Edit: Probiert - daran liegts aber nicht :(


    Jetzt verdächtige ich den hier:

    VB.NET-Quellcode

    1. Private Sub dgvSubdirectories_SelectionChanged(sender As Object, e As System.EventArgs) Handles dgvSubdirectories.SelectionChanged
    2. myDebug("dgvSubdirectories_SelectionChanged", blnSubdirIXChangedEnabled)
    3. If Not blnSubdirIXChangedEnabled Then Exit Sub
    4. ResetMessages()
    5. ResetSort("F"c)
    6. LoadFileList(GetRealPath())
    7. UpdateCount("B"c)
    8. End Sub
    Also wenn die Selection changed, dann wird die FileList komplett neu befüllt.
    Jo, bei formübergreifendem Databinding kann dann auch im anderen Form in der FileList nix anneres angezeigt werden, als was halt in der FileList-DataTable drinne ist.

    Also wenn das ein DateiManager mit 2 Forms werden soll, muss man da glaub anders konzipieren.
    Man könnte das Datenmodell so erweitern, dass jedes Form seine eigenen Datensätze anzeigt (und ggfs. auch löscht).

    Also eben die Tatsache auch modellieren, dass hier 2 Forms existieren.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „ErfinderDesRades“ ()

    VB.NET-Quellcode

    1. If Not blnSubdirIXChangedEnabled Then Exit Sub


    Beim Laden der Form SubdirectoryList wird zig mal das Event "Selection Changed" gefeuert! Und ohne blnSubdirIXChangedEnabled = False wird jedes Mal die FileList völlig unnötig neu aufgebaut!

    Aber gut, dann nimm das halt heraus. Das hab ich übrigens auch schon probiert! An den grundlegenden Verhältnissen hat sich dadurch aber auch nix geändert! Wenn sich die Selection der SubdirList in der FormA ändert, dann wird die FileList in FormA UND FormB neu aufgebaut! Und das ist eben nicht richtig, weil sich die Auswahl der SubdirectoryListe in FormB nicht geändert hat!

    Ich habe nach wie vor gravierende Zweifel, ob das mit dem "Umstöpseln der DataSource" für dieses Vorhaben das richtige Vorgehen ist.

    Nimm doch einfach mal die Sache mit der Datenumstöpselei wech:

    VB.NET-Quellcode

    1. 'FormB.FileListBindingSource.DataSource = Me.DataSet1 'Combine source ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


    Jetzt rennt die Demo Anwendung OHNE jede Probleme !

    LG
    Peter

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Peter329“ ()

    Also, dann sollten wir nicht mehr um den heißen Brei herumreden !

    Halten wir das doch mal fest: formübergreifendes Databinding ist für dieses Anwendungsszenario schlicht und ergreifend NICHT möglich.

    Ich nehme also die Sache mit der Umstöpselei heraus. Wenn ich nun in einer Form Änderungen vornehme, und in beiden Forms gleiche Listen angezeigt werden, dann muss ich diese Änderungen in der "gegnerischen" Form bedarfsweise nachvollziehen. Das hatte ich bereits ja auch so programmiert und das ist gar nicht mal viel Coding, wenn man es geschickt anstellt:

    Die Routinen die Änderungen vornehmen (Create, Rename, Copy, ...) rufen am Ende ihrer Verarbeitung genau EINE gemeinsame Routine auf: UpdateDataSource(...). Und diese Routine macht genau das was, ihr Name sagt. Damit werden dann auch die DataGridViews dieser Form automatisch aktualisiert. Arbeite mit Daten nicht mit Controls ... so hab ich das bei euch gelernt!

    Der Update der "gegnerischen" Form ist jetzt aber sehr einfach: Die jeweils andere Form habe ich mit "alternate Form" addressiert. Und damit kann ich am Ende von UpdateDataSource(...) jetzt diese Routine rekursiv auch in der "gegnerischen" Form aufrufen, wenn es Überschneidungen gibt:

    VB.NET-Quellcode

    1. Public Sub UpdateDataSource(chrType As Char, chrFunction As Char, strRealToObject As String,
    2. blnReplace As Boolean, lngOldSize As Long, blnReinit As Boolean)
    3. 'Update my data source
    4. '...
    5. 'Update alternate data source
    6. If Not blnReinit Then Exit Sub ' 'Avoid recursion loop
    7. If intWindow = 0 Then Exit Sub ' 'No alternate window open - no echo required
    8. If chrType = "S"c AndAlso RealBasePath <> alternateForm.RealBasePath Then Exit Sub ' 'Different subdirectory lists - no echo required
    9. If chrType = "F"c AndAlso GetRealPath() <> alternateForm.GetRealPath() Then Exit Sub ' 'Different file lists - no echo required
    10. alternateForm.UpdateDataSource(..., blnReinit:=False) ' 'Reinvoke update for alternate form (recursion)
    11. End Sub


    Das sind gerade mal 5 Zeilen Code ... und - oh Wunder - es funktioniert!

    Mein Problem mit dem "Erzwingen der Synchronisation" hat sich in Luft aufgelöst! Ich hatte ganz einfach UpdateDataSource(...) statt alternateForm.UpdateDataSource(...) kodiert ... und damit wurde der Update nochmal in der originären und nicht in der "gegnerischen" Form ausgeführt. Ein kleiner aber gemeiner Fehler, weil man beim tracen nicht unbedingt gleich merkt, dass man in der falschen Form läuft, weil sie ja genau gleich aussehen. Manchmal muss man über die Dinge halt mal sprechen. :)

    Trotzdem bin ich sehr dankbar über die Diskussion mit euch. Denn jetzt verstehe ich die Sache mit der "Umstöpselei" viel besser ... wann sie Sinn macht ... und wann man das eben nicht einsetzen kann!

    LG
    Peter

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Peter329“ ()

    Ach so, eh ich das jetzt vergesse:

    Ich hatte gefragt, wie man beim DataBinding die Synchronisation zwischen DataSource und DataGridView "erzwingen" kann. Die Antwort ist ganz einfach:

    Es gibt keine Notwendigkeit die Synchronisation zwischen DataSource und DGV zu "erzwingen"!

    Wenn die DataSource sich ändert, wird die DataGridView angepasst. Und wenn die DGV sich nicht ändert, dann einfach deshalb, weil es keine Änderung an der DataSource gibt. Punkt! So profan das klingen mag, aber das ist eine der wesentlichen Erkenntnisse, die ich aus dieser Diskussion gewonnen habe. :)

    Man muss sich mit diesem Hobel "DataBinding" beschäftigen, um zu lernen, wie man damit umgeht. Und wie immer lernt man das nur, indem man eben mit diesen Konstrukten arbeitet. Also nochmal, herzlichen Dank für eure unendliche Geduld ... vielleicht gehe ich euch auf die Nerven ... aber letztendlich habe ich durch euch eine Menge gelernt!

    LG
    Peter

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