Benachrichtigung bei ObservableCollection fehlt.

  • WPF

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

    Benachrichtigung bei ObservableCollection fehlt.

    Hallo Leute,
    es ist mir wohl bekannt, dass das gar nicht gerne gesehen wird wenn man die gleiche Frage in verschiedene Foren postet. Ja ist ja klar!
    Ich erlaube mir trotzdem, ausnahmsweise gegen diese Regel zu verstoßen! Aber nicht ohne Grund. Vor ein paar Tage hab ich meine Frage nämlich schon einmal in einem anderen Forum gepostet und erst im nachhinein bemerkt, dass die letzte Antwort auf eine Frage vom 1. April stammt.....
    Ich hoffe das nimmt also keiner mir übel.

    Die Fragen auf die ich eine Antwort suche sind im Zusammenhang mit der ObservableCollection(Of T)-Klasse.
    Bei MSDN steht zu dem Thema folgendes geschrieben: Stellt eine dynamische Datenauflistung dar, die Benachrichtigungen bereitstellt, wenn Elemente hinzugefügt oder entfernt werden oder wenn die gesamte Liste aktualisiert wird.
    Das klang so vielversprechend, dass ich mir ein WPF Projekt angelegt habe um zu sehen ob sogar ich mittels dieser Klasse, mit meinen bescheidenen Kenntnissen, ein schönes Projekt erschaffen könnte.
    Ich musste aber leider sehr schnell feststellen, dass das doch ein gewisses Mass an Fachkenntnissen verlangt.
    Und jetzt bin ich an dem Punkt angelangt wo ich trotz Google, MSDN un co nur noch im Kreis rumdrehe.....

    Ich versuche mal so gut ich kann mein Projekt mit meinen eigenen Worten zu beschreiben.
    Es handelt sich um ein WPF Projekt mit Visual Studio 2015. Die Daten welche die Desktopanwendung bearbeiten soll stammen aus einer SQL Datenbank mit gleich 2 Tabellen, welche in einer "1 to n parent/child" Relation zueinander stehen.
    Diese Daten werden im Projekt als Entity Model bereitgestellt. Oder müsste ich doch besser sagen, dass das Model aus der .MDF Datei erstellt wurde und mit zum Projekt gehört.
    Die Datensätze sollen dann schlussendlich in einem ListView dargestellt werden. Und der Gedanke war eigentlich der, dass beim löschen oder hinzufügen eines "Datensatzes" das Element im UI (das besagten ListView) das gleich mit bekommen sollte und dann auch gleich die Änderungen anzeigen sollte.
    Dank der in der ObservableCollection-Klasse bereitgestellten INotifyCollectionChanged und INotifyPropertyChanged Schnittstellen hatte ich mir viel weniger Schwierigkeiten erwartet.
    Und jetzt habe ich natürlich viele Fragen an euch.
    Erstens, kann mit der oben beschriebenen "Konstellation" in meinem Projekt mittels der ObservableCollection(Of T)-Klasse erreicht werden, dass ohne viel Programmierungs-Aufwand, eine funktionierende Anwendung entstehen kann, welche vom User durchgeführten Änderungen sofort an das ListView Element "weiter leitet"?
    Oder gilt das nur unter bestimmten Bedingungen? (vielleicht nicht bei Verwendung eines Entity Models?) Muss trotz des Entity Models noch zusätzlich eine "Daten Klasse" welche von NotifyPropertyChanged "erbt", so ähnlich wie es im Tutorial namens "MVVM-Anwendungs-Struktur" hier bei VB-Paradise mit der Klasse "Person" vorgeführt wird, hinzugefügt werden?
    Oder, stimmt die Idee doch, und es liegt an Fehlern in meinem Projekt, dass das mit der "Benachrichtigung" nicht so gut klappt?
    Und was mir auch nicht klar ist, wo sollen eventuelle Datenänderungen überhaupt durchgeführt werden? Beim Löschen eines Datensatzes, muss der aus dem Entity Model entfernt werden oder eher aus der ObservableCollection?
    Wie ihr seht, ist mir noch vieles unklar...
    So, jetzt versuche ich noch ein paar Code-Ausschnitte zu posten. Mit deren Hilfe erkennt ihr mein Vorhaben bestimmt besser...

    XML-Quellcode

    1. <Window.Resources>
    2. <CollectionViewSource x:Key="TodosView"/>
    3. <!--<CollectionViewSource x:Key="StagesView" Source="{Binding Source={StaticResource TodosView}, Path='Stages'}" />-->
    4. <CollectionViewSource x:Key="StagesView" Source="{Binding Stages, Source={StaticResource TodosView}}" />
    5. <!--<my:DataClass x:Key="viewMod" />-->
    6. </Window.Resources>
    7. <Grid DataContext="{Binding Source={StaticResource TodosView}}">
    8. .
    9. .
    10. .


    Und hier noch dien ersten Zeilen aus dem Code behind des MainWindows:

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Class MainWindow
    3. Public TodosEntities As RelatedTablesEntities
    4. Public cvsTodos As New CollectionViewSource
    5. Public TodosdData As ObservableCollection(Of Todo)
    6. Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
    7. TodosEntities = New RelatedTablesEntities()
    8. TodosdData = New ObservableCollection(Of Todo)(TodosEntities.Todos)
    9. 'TodosdData = New ObservableCollection(Of Todo)(From t In TodosEntities.Todos.Include("Stages"))
    10. cvsTodos = CType(Me.Resources("TodosView"), CollectionViewSource)
    11. cvsTodos.Source = TodosdData
    12. End Sub
    13. .
    14. .
    15. .

    Ich danke euch schon im Voraus für eure Hilfe. Ich bin für jeden Vorschlag, Hinweis oder sonstiger Tip sehr dankbar.
    Jeiss

    Jeiss schrieb:

    Ich bin für jeden Vorschlag, Hinweis oder sonstiger Tip sehr dankbar.
    WPF ist nicht so meins.
    Aber ich könnte MSDN zitieren.
    Vielleicht ist da ein Tipp für dich versteckt oder es bringt andere auf die richtige Spur:
    Notes on XAML Usage
    ObservableCollection(Of T) can be used as a XAML object element in Windows Presentation Foundation (WPF), in versions 3.0 and 3.5. However, the usage has substantial limitations.

    ObservableCollection(Of T) must be the root element, because the that must be used to specify the constrained type of the genericObservableCollection(Of T) is only supported on the object element for the root element.

    You must declare an (which entails that the build action for this XAML file must be Page or some other build action that compiles the XAML).

    ObservableCollection(Of T) is in a namespace and assembly that are not initially mapped to the default XML namespace. You must map a prefix for the namespace and assembly, and then use that prefix on the object element tag for ObservableCollection(Of T).

    A more straightforward way to use ObservableCollection(Of T) capabilities from XAML in an application is to declare your own non-generic custom collection class that derives from ObservableCollection(Of T), and constrains it to a specific type. Then map the assembly that contains this class, and reference it as an object element in your XAML

    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    ich würd v.a. empfehlen, sich zunächstmal mittm MVVM-Pattern zu beschäftigen - eine so rohe Anwendung sollte noch vollkommen ohne CodeBehind auskommen.
    Sieh dich dazu mal im Wpf-Tut-Bereich um, etwa Grundlagen - MVVM-Anwendungs-Struktur
    Ein Sample mit EF ist hier: EntityFramework-CodeFirst-Sample

    Insgesamt denke ich, ist man als Einsteiger gleich überfordert, wenn man beides auf einmal stemmen will: MVVM + EF-Datenbank-Anbindung.
    Hallo petaod, hallo ErfinderDesRades,
    ​ich danke euch für eure Hilfe.
    Ja ist wohl das Beste was ich tun kan, mich an die Tut's zu halten und mich davon zu inspirieren. Das kann ja noch lustig werden!
    Aber bevor ich mich da hinein arbeite, auf eine Frage weiß ich wirklich keine Antwort. Womöglich gibt es, wie immer verschiedene Möglichkeiten, abhängig von dem was man erreichen will.
    Nehmen wir mal das Tutorial ​MVVM-Anwendungs-Struktur aus den vb-Paradise Grundlagen als Beispiel.
    In dem Tut wird im MainWindow eine ListBox an die Persons aus dem MainModel gebunden. Ist bestimmt ok so. Aber angenommen einige dieser Persons wären erwachsen und hätten "children"? Wie es in meinem Projekt ja der Fall ist. Eine Tabelle mit den Parent-Daten und eine zweite mint den Child-Daten (1 to n relation). Bei mir werden die Daten aus der SQL Datei, welche die beiden Tabellen enthält, in ein Entity Model "geladen". Wenn eine zweite ListBox im Mainwindow nun die child-Daten anzeigen soll, wäre es dann von Vorteil eine zweite ​ListCollectionView mit den Child-Daten, also eine ListCollectionView mit einer ObservableCollection (of Children) im MainModel vor zu sehen? Oder wäre das überflüssig, da das Entity Model ja auch über die 1 to n Relation beider Tabellen "Bescheid weiß"?
    Es würde mir sehr weitehelfen, wenn mich jemand in dieser Frage beraten könnte.

    Danke im Voraus,
    Jeiss
    prinzipiell beherrscht der ObjectContext derlei dinge.
    guck dir das EF-Tut - da ist ja nicht nur eine 1:n-Relation präsentiert, sondern es sind deren zwei, nämlich eine m:n - Relation.

    Welche ja - aufgelöst in ihre 1:n-Bestandteile so darstellbar wäre:

    Category => Article
    Supplier => Article

    Wie man das im Viewmodel umsetzt, da streiten sich die Gelehrten. Ich habe direkt die DbSets des EF als DataSource hergenommen, denn die können sowas.
    Andere sagen, direkt an den EF-ObjectContext binden ist böse, man muss die Daten umfüllen in eigene Viewmodel-Klassen (was allerdings auch problematisch ist, denn es gibt keine Auflistungen ausser DbSets und typisiertes Dataset, die m:n-Relationen widerspruchsfrei präsentieren können - aber das ist eine viel weitergehende Diskussion).
    Jedenfalls OOP gedacht: Wenn eine Person Kinder hat, dann bekommt die Person-Klasse logischerweise eine Listen-Property, wo man die Kinder "ablegen" kann.
    Und das kann man auch im Xaml binden - entweder als Treeview, oder mit dem 2. Datagrid, als Parent-Child-View.
    Bin mir nicht sicher, ob das das ist, was Du suchst, aber ich verweise jetzt einfach mal auf das hier:
    auf List(of).add reagieren
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hallo ErfinderDesRades,
    Angucken kann ich mir das Ef-Tut schon, bloß starten kann ich es nicht! Erhalte andauernd die gleiche Fehlermeldung. Nicht mal die "MostSimple"-Variante läuft auf meinem Rechner. Habe zwei VS-Versionen probiert, die 2013 und die 2015, ohne Erfolg. Die Antworten auf die ich im Net gestoßen bin....naja bin mir nicht sicher ob die für mich zutreffen. Hier mal die Fehlermeldung, vielleicht kannst du etwas damit anfangen.

    Zusätzliche Informationen: The ADO.NET provider with invariant name 'System.Data.SqlServerCe.4.0' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.
    Der Fehler tritt im MainViewModel hier auf:

    VB.NET-Quellcode

    1. Private Sub ConnectDataContext()
    2. _context = WarehouseContext.Instance
    3. Article = _context.Article.Local
    4. Category = _context.Category.Local
    5. Supplier = _context.Supplier.Local
    6. End Sub

    In der Zeile:

    VB.NET-Quellcode

    1. Article = _context.Article.Local


    Danke,
    Jeiss