Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   .NET-Framework (managed code) (https://www.delphipraxis.net/79-net-framework-managed-code/)
-   -   C# MVVM - ViewModel 1:n Beziehung (https://www.delphipraxis.net/190957-mvvm-viewmodel-1-n-beziehung.html)

Neutral General 23. Nov 2016 13:15

MVVM - ViewModel 1:n Beziehung
 
Hallo,

Ich hoffe einfach darauf dass es hier jmd. gibt der mir helfen kann.
Bin was MVVM angeht kompletter Neuling und bin mir momentan nicht sicher wie man folgendes richtig lösen würde:

Mein Fenster soll mehrere Dokumente darstellen können (1 Doc pro Tabsheet). Jedes dieser Dokumente enthält mehrere Elemente.
Das ganze soll nun in MVVM abgebildet werden. Mein Ansatz war bisher folgender:

Mein Fenster:
Code:
<Window ...>
    <Grid>
        <views:DocumentView/>
    </Grid>
</Window>
DocumentViewModel:
Code:
public class DocumentViewModel
{
    public ObservableCollection<DocumentModel> Documents
    {
        get; private set;
    }
   
    public DocumentViewModel()
    {
        Documents= new ObservableCollection<DocumentModel>();
    }
}
DocumentModel:
Code:
public class DocumentModel : DependencyObject
{
    public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(DocumentModel), new PropertyMetadata("Untitled"));
    public static readonly DependencyProperty FilenameProperty = DependencyProperty.Register("Filename", typeof(string), typeof(DocumentModel), new PropertyMetadata(""));
   
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    public string Filename
    {
        get { return (string)GetValue(FilenameProperty); }
        set { SetValue(FilenameProperty, value); }
    }
}
DocumentView:
Die DocumentView stellt die Liste von Dokumenten aus dem ViewModel in einem PageControl dar.
Ich nutze Avalondock, vereinfache das XAML hier aber zu einem Pseudo-PageControl um das ganze übersichtlich zu halten.
Der Inhalt der Document-Tabsheets wird mit DocumentElementViews dargestellt.
Code:
<UserControl>
    <UserControl.DataContext>
        <viewModels:DocumentViewModel/>
    </UserControl.DataContext>

    <UserControl.Resources>
        <DataTemplate DataType="{x:Type viewModels:DocumentElementViewModel}">
            <views:DocumentElementView/>
        </DataTemplate>
    </UserControl.Resources>

    <PageControl DocumentSource="{Binding Documents}">
        <PageControl.TabHeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}"/>
            </DataTemplate>
        <PageControl.TabHeaderTemplate>

        <PageControl.TabContentTemplate>
            <DataTemplate>
                <ContentControl>
                    <ContentControl.Content>
                        <viewModels:DocumentElementViewModel/> <!-- PROBLEM! -->
                    </ContentControl.Content>
                </ContentControl>
            </DataTemplate>
        </PageControl.TabContentTemplate>
    </PageControl>
</UserControl>
Wo ich jetzt nicht genau weiß was ich tun soll ist in der mit "<!-- PROBLEM! -->" markierten Zeile.
Das DocumentElementViewModel muss die Elemente des Documents aus der Datei laden und benötigt dafür den Dateinamen.
Wie kann ich jetzt den Dateinamen an das DocumentElementViewModel weitergeben? Ich kann dem DocumentElementViewModel natürlich eine Property "DocumentFilename" verpassen und dann
im XAML in der markierten Zeile folgendes tun:
Code:
<viewModels:DocumentElementViewModel DocumentFilename="{Binding Filename}"/>
Aber ist das der richtige Weg? Gehört der DocumentFilename in das viewModels:DocumentElementViewModel obwohl es ja schon im DocumentModel enthalten ist?
Ich müsste das Laden der Elemente dann im PropertyChanged von DocumentFilename anstoßen.

Nachdem ich mich im Internet etwas umgeschaut hat sollte man allerdings seine ViewModels miteinenader verbinden.
Also soll ich im DocumentViewModel die Liste mit DocumentModels durch eine mit DocumentElementViewModel ersetzen? Aber dann bräuchte DocumentElementViewModel doch eine Property mit dem DocumentModel. Und dann ist irgendwie alles komisch verschoben.

Ich hoffe das ist nicht zu verwirrend. Ich bin nämlich verwirrt und weiß nicht genau wie ich so eine 1:n Beziehung zwischen 2 ViewModels (+ Views/Models) und die Datenübergabe vom ViewModel-Parent zu den n-ViewModel Kindern sauber im Sinne des MVVM-Patterns hinbekomme.

Ich bekomme das schon irgendwie hin, aber bei allem was ich mir überlege habe ich das Gefühl, dass es keine Lösung im Sinne des MVVM-Patterns ist.
Deshalb würde mich eine generelle Vorgehensweise interessieren.

Morphie 23. Nov 2016 16:20

AW: MVVM - ViewModel 1:n Beziehung
 
Kannst du die Hierarchie bitte noch einmal genau erklären?
Ich verstehe noch nicht genau den Unterschied zwischen DocumentViewModel und DocumentElementViewModel.
Die Implementierung von DocumentElementViewModel hast du uns auch noch nicht gezeigt.

Neutral General 23. Nov 2016 16:38

AW: MVVM - ViewModel 1:n Beziehung
 
DocumentViewModel ist das ViewModel für die Dokumente
DocumentElementViewModel ist das ViewModel für die Elemente in einem dieser Dokumente.

Die View des DocumentViewModels zeigt die im ViewModel enthaltenen Dokumente in einem PageControl an - Für jedes Dokument 1 Tabsheet.
An der markierten Stelle wird dann als Inhalt des Tabsheets ein DocumentElementViewModel erstellt, dass dann zusammen mit der DocumentElementView für die Verwaltung und Darstellung des Dokuments selbst verantwortlich ist.

Das Problem ist dass ich an irgendeiner Stelle meinem DocumentElementViewModel den Inhalt WELCHEN Dokuments es laden/darstellen soll mitteilen muss.
Und ich weiß nicht genau wo/wie. Ich KÖNNTE (rein theoretisch, aber keine Ahnung ob das so im Sinne von MVVM ist) dem in der XAML markierten Stelle erstellten DocumentElementViewModel eine "DocumentFilename"-Property verpassen und dann per Binding den FileName des DocumentModels an das DocumentElementViewModel binden und im PropertyChanged des DocumentFilename auf das Ändern des Dateinamen reagieren und alles benötigte laden.

Aber ist das im Sinne des Erfinders? Wie würde man sowas machen?

Edit: Die Implementierung von DocumentElementViewModel ist eigentlich nicht relevant. Diese Klasse ist momentan eigentlich noch mehr oder weniger leer.

Morphie 23. Nov 2016 16:49

AW: MVVM - ViewModel 1:n Beziehung
 
Habe ich das so richtig verstanden?
View > (n) Documents > (n) DocumentsElements?

Deine View soll mehrere Dokumente in einem PageControl anzeigen?
Jedes Dokument hat mehrere DocumentElements? Wie sollen die angezeigt werden?

Neutral General 23. Nov 2016 16:52

AW: MVVM - ViewModel 1:n Beziehung
 
Genau. Die Elemente werden letztendlich auf einem Canvas (bzw. ItemsControl mit Canvas als Panel) angezeigt, aber das ist wie gesagt nicht wirklich wichtig.
Das Problem besteht zu 99% darin dass ich nicht weiß wie ich am besten/saubersten den DocumentsElements mitteile welche Elemente es (woher) laden soll.
Wie diese Elemente jetzt letztendlich geladen oder dargestellt werden ist erstmal unwichtig.

Morphie 23. Nov 2016 17:04

AW: MVVM - ViewModel 1:n Beziehung
 
Ich glaube das ist aber kein Problem von MVVM...
Baue dir doch erst mal eine kleine Konsolenanwendung um die POCO-Klassen zu erstellen. Dann wirst du sehen welche Klasse für welche Aufgabe zuständig ist.
Denn das Laden der Daten hat nichts mit MVVM zutun, das müssen die POCO-Klassen (auch Models genannt) machen.

Denn das Laden von Daten gehört nicht in die Oberfläche, sondern in die Logik.

Ich vermute mal, dass ein Document für das Laden und erzeugen der DocumentElements zuständig ist. Passt das?

Wenn du die Logik abgebildet hast, dann kannst du die Oberfläche designen. Und da musst du dann wahrscheinlich relativ viel mappen...


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz