Ich habe eine Frage zu MVVM in WPF, die mich verrückt macht.
Warum so etwas machen:?
MainWindow.xaml:
<Window x:Class="MVVMProject.MainWindow"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
Haben Sie Ihre ExampleView.xaml eingerichtet als:
<ResourceDictionary xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<Grid>
<ActualContent/>
</Grid>
</DataTemplate>
</ResourceDictionary>
Und erstelle das Fenster so:
public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
MainWindow app = new MainWindow();
ExampleVM context = new ExampleVM();
app.DataContext = context;
app.Show();
}
}
Wenn du es so machen kannst:?
App.xaml: (Startfenster/Ansicht einstellen)
<Application x:Class="MVVMProject.App"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
StartupUri="ExampleView.xaml">
</Application>
ExampleView.xaml: (ein Fenster kein ResourceDictionary)
<Window x:Class="MVVMProject.ExampleView"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
>
<Window.DataContext>
<vms:ExampleVM />
</Window.DataContext>
<Grid>
<ActualContent/>
</Grid>
</Window>
Im Wesentlichen ist es "Als DataTemplate anzeigen" (VaD) vs. "Als Fenster anzeigen" (VaW)
Hier ist mein Verständnis des Vergleichs: (Hinweis: Ich verwende VS 2008, daher fehlt mir die Mischbarkeit und/oder anderes Material.)
Also, was ist hier los? Kann ich meine Fenster nicht einfach in XAML erstellen, über die Eigenschaften der VM sauber auf ihre Daten zugreifen und damit fertig werden? Der Code-Behind ist derselbe (praktisch null). Ich habe Probleme zu verstehen, warum ich das gesamte View-Material in ein ResourceDictionary mischen sollte. (Aber ich will es nicht falsch machen ;-))
Ist es überhaupt wichtig? Gibt es etwas, das ich verpasst habe? Vielen Dank fürs Lesen. :O
Vielen Dank an Rachel Lim und Nick Polyak für mein blühendes Verständnis von MVVM
Bearbeiten: Kleine Durchflussänderung
Die Benutzer verwenden DataTemplates
auf diese Weise, wenn sie Ansichten abhängig vom ViewModel dynamisch wechseln möchten:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:VM1}">
<!-- View 1 Here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- View 2 here -->
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding}"/>
</Window>
So,
ob Window.DataContext
ist eine Instanz von VM1
, dann View1
wird Angezeigt werden,
und wenn
Window.DataContext
ist eine Instanz von VM2
, dann View2
wird Angezeigt werden.
Zugegeben, es macht überhaupt keinen Sinn, wenn nur 1 View erwartet wird und sich nie ändert.
Ich hoffe das ist klar genug: P
Da in VaD die Ansichtsmodelle nichts über die Ansichten wissen, können Sie eine voll funktionsfähige Anwendung erstellen, die ausschließlich aus Ansichtsmodellen und keinen Ansichten besteht. Dies führt zu der Möglichkeit, eine Anwendung zu schreiben, die vollständig durch Code gesteuert werden kann. Dies führt wiederum zu der Möglichkeit, Integrationstests ohne die GUI durchzuführen. Integrationstests über die GUI sind notorisch anfällig - während Tests über Ansichtsmodelle robuster sein sollten.
Aus meiner persönlichen Erfahrung: Beide Arbeitsmodelle sind verfügbar, je nachdem, was Sie wollen und je nach den Anwendungsanforderungen. Die Idee hinter VaD
ist, den Inhalt und den Container zu dekopieren. Wenn Sie VaD
implementieren, können Sie diese Vorlage (standardmäßig) immer dann verwenden, wenn Sie Elemente dieses Typs anzeigen. Sie können es in ItemsControls
(Listen, Listenansichten, Rastern usw.) und in ContentControls
verwenden, um nur Bindungen zu erstellen. Wie Sie sagten, funktioniert VaD
, um den Inhalt des Fensters zu wechseln, ohne ein neues zu schließen und zu öffnen. Sie können die Ansicht auch mit UserControls
definieren, dann die Kontrolle über fokussierte Elemente übernehmen und den Code dahinter verwalten. Ihre Datenvorlage könnte also so aussehen:
<ResourceDictionary xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
<CustomUserControl A="{Binding A}" B="{Binding B}" DataContext="{Binding}" .../>
</DataTemplate>
Sie können auch in einem UserControl
Abhängigkeitseigenschaften festlegen, die den Job erleichtern, da das Binden und Entkoppeln der App möglich ist.
Aber natürlich ist es in Ordnung, VaW
für das Hauptfenster oder ein anderes Fenster zu verwenden, wenn Ihre App keine dynamische Inhaltsumschaltung erfordert. Tatsächlich können Sie sowohl VaW
als auch VaD
verwenden. Letzteres kann für innere Elemente in der App verwendet werden, für die keine Fenster erforderlich sind. Sie entscheiden, was für Sie besser ist, abhängig von den Anwendungsanforderungen und der Zeit, die für die Entwicklung der App zur Verfügung steht. Hoffe, diese persönliche Erfahrung hilft ...