Ich denke nicht, dass es ideal ist, dass Sie Ihre Anwendungsarchitektur als Beziehungen zwischen Ansichten dargestellt haben; Ich denke, ein besserer Weg, darüber nachzudenken, ist eine Reihe von Beziehungen zwischen den Viewmodels, wobei die Ansichten bei Bedarf von diesem Baum herunterhängen. Wenn Sie so darüber nachdenken, "wie werden Daten weitergegeben?" Wird viel einfacher. Eine Ansicht ist nur eine Verbindung zwischen einem Ansichtsmodell und dem Benutzer. Du entwirfst kein Haus als Fenster und Telefone und versuchst dann den Grundriss daraus zu bestimmen. Du beginnst damit, was das Haus macht und wie die Leute darin leben werden.
Das ist also einfach:
Einige Viewmodels haben eine AAViewModel
Eigenschaft. Es kann alle Arten von einfachen oder komplizierten Ansichten auf diesen Viewmodels geben; Wenn eine Ansicht den Benutzer die AAViewModel
Sachen des Viewmodels bearbeiten lassen möchte, dann enthält es eine AAView
, die passend an das Viewmodel AAViewModel
gebunden ist. Ihre MainViewModel
und DialogViewModel
sind beide große komplizierte interaktive Ansichten, die jemand ihre vms AAViewModel
Zeug bearbeiten lassen wollen.
Wenn MainViewModel
ist DialogViewModel
‚s Elternteil oder eine temporäre Instanz von DialogViewModel
erstellt nur in einem modalen Dialog zu setzen, dann würde MainViewModel
den Dialog zeigen, und hat einen Blick auf dialogVM.AAVM.CData.IsDirty
zu entscheiden, was damit zu tun. Oder vielleicht gibt es dialogVM.AAVM
eine neue CDataClass
Instanz vor dem Anzeigen des Dialogfelds (vielleicht ein Klon seiner eigenen Instanz), und wenn ShowModel()
true
zurückgibt, dann tut es etwas mit dialogVM.AAVM.CData
.
Der Punkt ist, dass, sobald Ihre Viewmodels alles fahren, wird es relativ einfach für sie miteinander zu kommunizieren. Eltern-Kind ist einfach: Eltern geben dem Kind Zeug und schauen, was das Kind zurückbringt. Ein Viewmodel kann das Ereignis PropertyChanged
eines anderen Viewmodels abonnieren. Ein Eltern-View-Modell kann seine Kinder überwachen. Wenn bei einem Kind etwas passiert, kann der Elternteil entscheiden, ob er ein Geschwister aktualisiert.Im Allgemeinen sollten Kinder nichts über ihre Eltern wissen; Dies macht es viel einfacher, Kind View-Modelle in unterschiedlichen Kontexten wiederzuverwenden. Es liegt an den Eltern zu entscheiden, was mit diesen Informationen zu tun ist.
Alle AAViewModel weiß, ist, dass jemand ihm eine Kopie von CDataClass
geben; Er aktualisiert seine öffentlichen Eigenschaften entsprechend. Dann übergibt ihm jemand anderes (wahrscheinlich AAView
, aber er weiß es nicht) einige Änderungen, indem er seine Eigenschaften einstellt; Er aktualisiert seine CDataClass
Instanz entsprechend. Nach einer Weile, die ihm unbekannt ist, kommt das eine oder andere Modell und schaut sich das CDataClass
an.
Die Kommunikation zwischen Ansichten und Viewmodels erfolgt über Bindungen.
UPDATE
Es stellt sich heraus, dass Sie Viewmodel in Ihren Ansichten, und als Ergebnis haben Sie keine Ahnung haben, sind zu schaffen, wie die Eltern, um sie zu bekommen. Und jetzt wissen Sie, warum es keine gute Idee ist, untergeordnete Ansichtsmodelle auf diese Weise zu erstellen.
Hier ist, wie Sie Kind Ansicht/Viewmodel in dem Viewmodel-zentriert Design ich oben beschrieben:
Zuerst loszuwerden, was auch immer du tust, das Kind Viewmodel in der Ansicht zu erstellen.
Zweitens eine DataTemplate
für die Art Kind Ansichtsmodell erstellen. Dies sollte in einem Ressourcenwörterbuch gehen, das mit den Ressourcen in App.xaml zusammengeführt wird, aber es ist so einfach, dass es Sie nicht tötet, wenn Sie faul werden und es einfach in die Resources
der zwei verschiedenen Ansichten einfügen, wo es verwendet wird.
Ich weiß nicht, wie Ihre Namespace-Deklarationen aussehen. Ich gehe davon aus, dass Ansichten in etwas sind, das xmlns:view="..."
genannt wird, und Viewmodels sind in etwas, das xmlns:vm="..."
genannt wird.
<DataTemplate DataType="{x:Type vm:AAAViewModel}">
<view:AAAView />
</DataTemplate>
Jetzt können Sie einen AAAViewModel
zum ContentProperty
jeglicher Kontrolle zuweisen, die von ContentControl
erbt (und das ist die meisten von ihnen), und die Vorlage instanziiert werden. Das bedeutet, dass XAML für Sie eine AAAView
erstellt und die Instanz AAAViewModel
der -Eigenschaft der AAAView
, die es gerade erstellt hat, zuweist.
Also lassen Sie sich AAAViewModel
als nächstes ein Kind erstellen, und dann werden wir es in der Benutzeroberfläche angezeigt.
public class DialogViewModel
{
// You can create this in DialogViewModel's constructor if you need to
// give it parameters that won't be known until then.
private AAAViewModel _aaavm = new AAAViewModel();
public AAAViewModel AAAVM
{
get { return _aaavm; }
protected set {
_aaavm = value;
OnPropertyChanged(nameof(AAAVM));
}
}
Und jetzt können wir AAAVM
in DialogView
anzuzeigen:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl
Content="{Binding AAAVM}"
Grid.Row="0"
/>
<StackPanel Orientation="Vertical" Grid.Row="1">
<!-- Other stuff -->
</StackPanel>
</Grid>
Nun, wie funktioniert MainViewModel
mit einem DialogViewModel
kontaktieren? Im Falle von Dialogen, da sie eine begrenzte Lebensdauer haben, ist es nicht wirklich eine große Sache, dass sie ihre eigenen Ansichtsmodelle erstellen können. Du kannst es so oder so machen. Ich lehne es generell an, es wie im zweiten Beispiel unten erstellen zu lassen.
Nicht ganz gleich, aber nah. Als Erstes werden Sie wieder los, was auch immer Sie tun, wenn der Dialog ein eigenes Ansichtsmodell erstellt.
MainViewModel.cs
public CDataClass CDC { /* you know the drill */ }
public void ShowDialog()
{
var dvm = new DialogViewModel();
// Maybe this isn't what you want; I don't know what CDataClass does.
// But I'm assuming it has a copy constructor.
dvm.AAAVM.CDC = new CDataClass(this.CDC);
if (DialogView.ShowDialog(dvm).GetValueOrDefault())
{
CDC = dvm.CDC;
}
}
Beachten Sie, dass das nächste Codebehind anzeigen, nicht Viewmodel ist.
DialogView.xaml.cs
public static bool? ShowDialog(DialogViewModel dvm)
{
var vw = new DialogView() { DataContext = dvm };
return vw.ShowDialog();
}
Nun Sie der Dialog fortsetzen lassen könnte sein eigenes Ansichtsmodell zu schaffen; in diesem Fall würden Sie es eine öffentliche Eigenschaft wie folgt geben:
public DialogViewModel ViewModel => (DialogViewModel)DataContext;
Und ein Showdialog-Methode wie folgt aus:
DialogView.xaml.cs
public static bool? ShowDialog(CDataClass cdc)
{
var dlg = new DialogView();
dlg.ViewModel.AAAVVM.CDC = cdc;
return dlg.ShowDialog();
}
Und dann könnte die Eltern interagieren mit es wie folgt statt:
MainViewModel.cs
public void ShowDialog()
{
var cdcClone = new CDataClass(this.CDC);
if (DialogView.ShowDialog(cdcClone).GetValueOrDefault())
{
CDC = cdcClone;
}
}
Schön und sauber.
Wenn dieser Dialog nicht modal ist, machen Sie das Dialogfeld viewmodel zu einem privaten Mitglied von MainViewModel
, und lassen Sie sich Ereignisse im Dialog ViewModel abonnieren, um auf dem Laufenden zu bleiben, was der Dialog macht. Immer wenn der Benutzer die Kopie des Dialogs von CDataClass
aktualisiert, würde der Dialog DataClassUpdated
auslösen, und MainViewModel
würde einen Handler für dieses Ereignis haben, der bei _dialogViewModel.AAAVM.CDC
schnüffelt und entscheidet, was damit zu tun ist. Wir können dafür bei Bedarf Beispielcode bekommen.
So jetzt können Sie sehen, was ich meine, indem ich alles in Bezug auf Eltern/Kind Viewmodels aufbaute, und sie in Views stopfte, wenn und wie passend.
Wenn die Daten von CDataClass zwischen diesen beiden Ansichten unterschiedlich sind, dann sind sie im Grunde getrennte Instanzen, nicht wahr? – Steve
http://StackOverflow.com/q/3801681/2470362 –