none
CollectionViewSource : bei veränderter Source aktualisiert sich der View nicht - Teil 2 RRS feed

  • Frage

  • Hallo zusammen,

    ich hatte bereits die Frage "CollectionViewSource : bei veränderter Source aktualisiert sich der View nicht" Mitte Mai gestellt und bin dann aber leider aufgrund von "Projekt-Dynamiken" (= die Projekt-Anforderungen mutieren und der Tag hat weiterhin nur 24 Studen ;-) leider nicht dazu gekommen, die Vorschlähe von Herrn Fleischer zu kommentieren.

    Das hole ich hier zuerst einmal nach : erst einmal Danke für die Antwort und das Bemühen die Problemstellung zu erfassen und zu lösen. Nur hat mir die Antwort dort leider nicht wirklich geholfen, da sie einen anderen Fokus als die Problemstellung hatte - ein Viewmodell mit einer Liste von Objekt ist nun mal etwas anderes als eine Entity-Table eines "LINQ to SQL" Datacontext. Und genau dort vermutete ich ja den "Fehler" bzw. ein mir fehlendes Verständnis für die Abläufe.
    Was meine Lösung betrifft : die Aufgabenstellung hatte sich "auf einmal" geändert und ich musste für den dort beschriebenen Fall eine ObservableCollection von Datenobjekten (Instanzen von .Net Klassen und nicht mehr LINQ to SQL Entities) verwenden - und sie da, dass Problem war nicht mehr vorhanden.

    Nun habe ich aber in einem anderen Projekt wieder an eine ähnlichen Aufgabenstellung und erlebe wieder dasselbe "Phänomen" - diesmal aber nur mit 1 Window. Ich beschreibe dies nun in einem neuen Thread, da die Antwort und eine Zusattzfrage zu weit vom eigentlich Problem weg geführt hat und dies beim Nachvollziehen einen zu sehr irritieren könnte.

    Also worum geht's : eine WPF Anwendung (.Net Framework 3.5 SP1) die das WPF-Toolkit und dessen DataGrid verwendet sowie einen SQL Server 2008 Express Datenbank auf die mittels "LINQ to SQL" zugegriffen wird.

    Die Architektur an der "Problem-Stelle" (mit soetwas haben also nicht nur Menschen "zu kämpfen", die "äußersten Wert / Fokus" auf Äußerlichkeiten legen ;-) :

    • In den Reourcen des Window ist eine CollectionViewSource definiert : CvsDetails
    • das Window verwendet ein DataGrid, das über ItemsSource an CvsDetails gebunden ist
    • im Code-Behind (C# by the way) wird nun bei der Änderung des Master Entity eine Methode UpdateBindings aufgerufen, welche die Source der CVS neu setzt : 
      icvcDetails.Source = iMaster.Details
      wobei iMaster eine LINQ to SQL Entity-Table und sein Property Details ein EntiySet ist.
      und schließlich der View der CVS in einem weiteren Instanzfeld gespeichert wird :
      iblcvDetails = (BindingListCollectionView) icvsDetails.View

    Nun die Abläufe, wo das Problem zu Tage tritt :

    • es soll eine Menge von Daten von einem XML-File importiert werden. Das Einlesen in einen Dataset und das Iterieren über die DataTable kein Problem
    • nun wird für jedes importierte Datum (XML Element) ein "Linq to SQL" Entity erzeugt :
      lDetailEntity = new DataContext.Detail()
      und anschließend mit den importierten Werten initialisiert und schließlich dem EntitySet des Masters hinzugefügt :
      iMaster.Detail.Add( lDetailEntity )
    • das funktioniert alles Prima und man kann die Daten bzw. neu erzeugten Entites auch in die Datenbank speichern
    • ABER die neuen Detail Entites erscheinen nicht in dem DataGrid
    • sie erscheinen erst in dem DataGrid, wenn ich die Anwendung beende und neu starte - was beweist, dass die Daten richtig gespeichert wurden und auch die Verweise auf die beteiligten Entities richtig gesetzt sind

    Was mir nicht "einleuchtet" :

    • die CollectionViewSource, die an das DataGrid gebunden ist, hat als Source "iMaster.Detail" gesetzt
    • ich füge genau diesem EntitySet die neuen Detail-Entities hinzu
    • und sie werden dennoch nicht in dem DataGrid angezeigt

    Was auch nicht funktioniert (theoretische Lösung Nr. 1) :

    • nachdem alle Detail-Entities erzeugt und dem Entity-Set "iMaster.Detail" hinzugefügt wurde
    • rufe ich die oben beschriebene UpdateBindings Methode auf, die also explizit das Source Property der CollectionViewSource auf iMaster.Detail setzt und anschließend den View der CVS neu abruft und in ein Instanzfeld speichert
    • und trotzdem erscheinen die neuen Entities nicht in dem Grid
    • was der Debugger aber an der Stelle zeigt ist, dass nicht nur "iMaster.Detail" die neuen Entities enthält, sondern auch die Source der CollectionViewSource ABER der View, der ja auch neu geholt wurde, hat weiterhin die Anzahl 0. Genau an dieser Stelle denke ich, fehlt mir ein Verständis für den richtigen Umgang mit CollectionViewSource in Zusammenhang mit "LINQ to SQL".
    • Wie kann es sein, dass das Source-Properties einer CollectionViewSource z.B. 256 Elemente hat und das View Property nur 0 Elemente. Auch ein Refresh auf den View bringt keine "Besserung".

    Eine Lösung, die zwar funktioniert, mich aber nicht zufrieden stellt :

    • anstatt die neuen Detail Entities über den Konstruktor der generierten "LINQ to SQL" Klasse zu erzuegen werden sie über die AddNew Methode der BindingListCollectionView erzeugt
    • und nachdem alle Werte aus dem XML-Element in das Entity übertragen wurde, wird mittels CommitNew die Hinzufügen-Transkation abgeschlossen
    • dabei wird das Detail-Entity auch in den EntitySet des Master eingetragen und es lässt sich alles "prima speichern" UND das Grid zeigt die neuen Detail-Entites an

    Soooo, ich hoffe war jetzt nicht zu lang, dennoch klar genug formuliert und ihr könnt das eigentliche Problem nachvollziehen.
    Ich würde mich wirklich tierisch freuen, wenn mir jemand meine Verständnis-Lücke auffüllen kann ...

    Vielen Dank für die Bemühung eurer Gehirnzellen im Voraus

     

     

    Freitag, 25. Juni 2010 09:13

Antworten

  • Ich löse dieses Problem, indem ich an im ViewModel vorhandene Eigenschaften vom Typ IColectionView binde. Mit PropertyChanged kann dann problemlos die Oberfläche zum Aktualisieren der Anzeige anregen.

    --
    Viele Gruesse
    Peter

    Montag, 5. Juli 2010 10:15
  • Hallo Zusammen,

    ich war leider so eingespannt, dass ich diese Frage hier ganz vergessen hatte und vor allem es versäumt habe die mir zwischenzeitlich "eingefallene" Lösung des Problems zu posten.

    Vor lauter Bäumen habe ich bei dem Problem mal wieder nicht den Wald gesehen - soll heißen die Komplexität des Zusammenhangs mit 2 Fenstern und XML Datei usw hat die Sicht auf das Naheliegende vernebelt.

    Die Ursache des Problems ist ganz einfach und wie man so schön sagt "by design". Denn die Entity-Sets bzw. die Klasse System.Data.Linq.Table<T> von "LINQ to SQL" implementiert kein "INotifyPropertyChanged", womit die CollectionViewSource die neu hinzugefügten Entities gar nicht mitbekommen kann.

    Viele Grüße

    Update : die Ursache ist natürlich nicht das missing "INotifyPropertyChanged" sondern das missing "INotifyCollectionChanged".

    • Als Antwort markiert devaai Donnerstag, 16. September 2010 14:34
    • Bearbeitet devaai Dienstag, 21. September 2010 11:48 Name der Schnittstelle korrigiert
    Donnerstag, 16. September 2010 14:34

Alle Antworten

  • Ich löse dieses Problem, indem ich an im ViewModel vorhandene Eigenschaften vom Typ IColectionView binde. Mit PropertyChanged kann dann problemlos die Oberfläche zum Aktualisieren der Anzeige anregen.

    --
    Viele Gruesse
    Peter

    Montag, 5. Juli 2010 10:15
  • Hallo Zusammen,

    ich war leider so eingespannt, dass ich diese Frage hier ganz vergessen hatte und vor allem es versäumt habe die mir zwischenzeitlich "eingefallene" Lösung des Problems zu posten.

    Vor lauter Bäumen habe ich bei dem Problem mal wieder nicht den Wald gesehen - soll heißen die Komplexität des Zusammenhangs mit 2 Fenstern und XML Datei usw hat die Sicht auf das Naheliegende vernebelt.

    Die Ursache des Problems ist ganz einfach und wie man so schön sagt "by design". Denn die Entity-Sets bzw. die Klasse System.Data.Linq.Table<T> von "LINQ to SQL" implementiert kein "INotifyPropertyChanged", womit die CollectionViewSource die neu hinzugefügten Entities gar nicht mitbekommen kann.

    Viele Grüße

    Update : die Ursache ist natürlich nicht das missing "INotifyPropertyChanged" sondern das missing "INotifyCollectionChanged".

    • Als Antwort markiert devaai Donnerstag, 16. September 2010 14:34
    • Bearbeitet devaai Dienstag, 21. September 2010 11:48 Name der Schnittstelle korrigiert
    Donnerstag, 16. September 2010 14:34