88 votes

WPF MVVM Pourquoi utiliser ContentControl + DataTemplate Views plutôt que des vues de fenêtre XAML directes?

J'ai une question à propos de MVVM en WPF qui est le moteur me batty.

Pourquoi faire quelque chose comme ceci:?

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>

Votre ExampleView.xaml mis en place comme:

<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>

Et de créer la fenêtre comme ceci:

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();
    }
}

Lorsque vous pouvez le faire comme ceci:?

App.xaml: (Set de démarrage de la fenêtre/Afficher)

<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: (une Fenêtre pas un 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>

Essentiellement, c'est "Vue comme DataTemplate" (VaD) et de "Vue de la Fenêtre" (Vff)

Voici ma compréhension de la comparaison: (Remarque j'utilise VS 2008 donc je manque Blendability et/ou d'autres trucs)

  • VaD: vous Permet de changer de Vue sans fermer la fenêtre. (Ce n'est pas souhaitable pour mon projet)
  • VaD: VM sait absolument rien sur la Vue, tandis que dans la Violence contre les femmes (seulement) doit être en mesure d'instancier lors de l'ouverture d'une autre fenêtre
  • Violence contre les femmes: je peux effectivement voir mon xaml rendus dans le Concepteur (je ne peux pas avec VaD, au moins dans mon installation actuelle)
  • Violence contre les femmes: Fonctionne de manière intuitive avec l'ouverture et la fermeture de windows; chaque fenêtre a (est) une Vue correspondante (et ViewModel)
  • VaD: ViewModel peut passer le long de la fenêtre initiale de la largeur, la hauteur, la possibilité d'agrandir etc. par le biais des propriétés (alors que dans la Violence contre les femmes, ils sont directement mis dans la Fenêtre)
  • Violence contre les femmes: Pouvez définir FocusManager.FocusedElement (pas sûr de la façon de VaD)
  • Violence contre les femmes: Moins de fichiers, depuis ma fenêtre types (par exemple, du Ruban, de la boîte de Dialogue) sont incorporés dans leurs points de Vue

Alors que ce passe ici? Je ne peux pas juste de construire mon windows en XAML, d'accéder à leurs données proprement via les propriétés de la VM, et être fait avec elle? Le code-behind est le même (presque nul). J'ai du mal à comprendre pourquoi je devrais lecture aléatoire de toutes la Vue des choses dans un ResourceDictionary. ( Mais je ne veux pas faire de mal ;-) )


Est-il encore de l'importance? Il y a une chose que j'ai manqué? Merci beaucoup pour la lecture. :O


Merci à Rachel Lim et Nick Polyak pour mon épanouissement compréhension de MVVM

Edit: faible flux de changement

140voto

HighCore Points 23088

Les gens utilisent DataTemplates , quand ils veulent passer dynamiquement points de Vue en fonction du ViewModel:

<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>

Donc,

si Window.DataContext est une instance de l' VM1, alors View1 sera affiché,

et si

Window.DataContext est une instance de l' VM2, alors View2 sera affiché.

Accordé, il n'a aucun sens si seulement 1 point de Vue est prévu, et n'a jamais changé.

J'espère que c'est assez clair :P

8voto

Phillip Ngan Points 4303

Comme dans VaD, les modèles de vues ne connaissent rien des vues, vous pouvez créer une application entièrement fonctionnelle entièrement composée de modèles de vues et pas de vues. Cela conduit à la possibilité d'écrire une application qui peut être entièrement pilotée par un code. Cela conduit à la possibilité d'effectuer des tests d'intégration sans l'interface graphique. Les tests d'intégration via l'interface graphique sont notoirement fragiles - alors que les tests via les modèles de vues devraient être plus robustes.

5voto

Raul Otaño Points 2122

De mon expérience personnelle: Les deux modèles de travail sont aviables, en fonction de ce que vous voulez, et en fonction des besoins de l'application. L'idée derrière le VaD est decopling le contenu et le contenant. Si vous implémentez VaD vous pouvez utiliser ce modèle (par défaut) lorsque vous le montrer tout élément de ce type. Vous pouvez l'utiliser en ItemsControls (listes, listviews, grilles, etc) et en ContentControls seulement de faire les liaisons. Comme vous l'avez dit, VaD travaux pour la commutation de la fenêtre de contenu avec la fermeture et l'ouverture d'une nouvelle. Vous pouvez également définir la vue à l'aide d' UserControls, puis vous prenez le contrôle si concentré d'éléments, et vous pouvez également gérer le code derrière. Donc, votre modèle de données peut être comme ceci:

<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>

Vous aussi vous en UserControl peut définir les propriétés de dépendance, c'est de rendre plus facile le travail, parce que permettent les liaisons et le découplage de l'application.

Mais bien sûr, si votre application ne nécessite pas de façon dynamique le contenu de commutation, il est possible d'utiliser VaW pour la fenêtre principale, ou de toute autre fenêtre. En fait, vous pouvez utiliser les deux VaW et VaD. Ce dernier peut être utilisé pour l'intérieur des éléments dans l'application, qui ne nécessite pas de windows. Vous shoose ce qui est mieux pour vous, en fonction des exigences de l'application, et le temps aviable pour le développement de l'application. Espérons que cette expérience personnelle aide...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X