web-dev-qa-db-fra.com

Concepts de base de MVVM - que doit faire un ViewModel?

En essayant de comprendre les concepts de MVVM, j'ai déjà lu plusieurs blogs et regardé quelques projets.

D'après ce que je comprends, un View est stupide, il sait juste comment présenter quelque chose qui lui est transmis.

Modèles ne sont que des données simples, et un ViewModel est quelque chose qui agit comme un remplissage entre les deux, qu'il devrait obtenir des informations de la Modèle = et passez-le sur le View, et le View devrait savoir comment le présenter. Ou inversement, si les informations de View changent, elles devraient être transmises au Model.

Mais je ne sais toujours pas comment appliquer le concept. Quelqu'un peut-il expliquer un scénario très simple pour que je puisse saisir le concept? J'ai déjà examiné plusieurs projets, mais cela n'a toujours pas de sens, donc si quelqu'un pouvait l'écrire en anglais, ce serait bien.

73
RKM

J'aime y penser de cette façon:

Les vues, comme vous le dites, sont stupides. Josh Smith, écrivain du séminal et souvent lié article MSDN sur MVVM, a déclaré que les vues sont "les vêtements que les données portent". Les vues ne contiennent jamais de données ni ne les manipulent directement, elles sont simplement liées aux propriétés et aux commandes de vos modèles de vue.

Les modèles sont des objets qui modélisent le domaine de votre application , comme dans les objets métier. Votre application est-elle un magasin de musique? Peut-être que vos objets modèles seront des artistes, des albums et des chansons. Votre application est-elle un navigateur d'organigramme? Vos objets modèles seront peut-être des managers et des employés. Ces objets de modèle ne sont liés à aucun type de rendu visuel, et ils ne sont même pas directement liés à l'application dans laquelle vous les placez - vos objets de modèle devraient avoir tout leur sens en tant que famille d'objets qui représentent une sorte du domaine. La couche modèle comprend également généralement des éléments tels que les accesseurs de service.

Cela nous amène à Viewmodels. Que sont-ils? Ce sont des objets qui modélisent une application GUI , ce qui signifie qu'ils fournissent des données et des fonctionnalités à utiliser par les vues. Ce sont eux qui définissent la structure et le comportement de l'application réelle que vous construisez. Pour les objets du modèle, le domaine est le domaine que vous choisissez (magasin de musique, navigateur d'organigramme, etc.), mais pour le modèle d'affichage, le domaine est une application graphique. Vos modèles de vue vont encapsuler le comportement et les données de tout ce que fait votre application. Ils vont exposer des objets et des listes en tant que propriétés, ainsi que des choses comme les commandes. Une commande n'est qu'un comportement (au plus simple, un appel de méthode) enveloppé dans un objet qui la transporte - cette idée est importante car les vues sont pilotées par la liaison de données, qui attache des contrôles visuels aux objets. Dans MVVM, vous ne donnez pas à un bouton une méthode de gestionnaire de clic, vous le liez à un objet de commande (servi à partir d'une propriété dans un modèle de vue) qui contient la fonctionnalité que vous souhaitez exécuter lorsque vous cliquez dessus.

Pour moi, les bits les plus déroutants étaient les suivants:

  • Même si les modèles de vue sont des modèles d'une application graphique, ils ne font pas directement référence ou n'utilisent pas de concepts visuels. Par exemple, vous ne voulez pas de références aux contrôles Windows dans vos ViewModels - ces choses vont dans la vue. ViewModels expose simplement les données et les comportements aux contrôles ou autres objets qui s'y lieront. Par exemple - avez-vous une vue avec un ListBox dedans? Votre modèle de vue contiendra certainement une sorte de collection. Votre vue a-t-elle des boutons? Votre viewmodel va presque certainement contenir des commandes.
  • Il existe quelques types d'objets qui pourraient être considérés comme des "modèles d'affichage". Le type de vue le plus simple à comprendre est celui qui représente directement un contrôle ou un écran dans une relation 1: 1, comme dans "l'écran XYZ a une zone de texte, une zone de liste et trois boutons, de sorte que le modèle de vue a besoin d'une chaîne, d'une collection, et trois commandes. " Un autre type d'objet qui tient dans la couche de modèle de vue est un enroulement autour d'un objet modèle qui lui donne un comportement et le rend plus utilisable par une vue - c'est là que vous entrez dans les concepts de couches de modèle de vue "épaisses" et "minces". Une couche de modèle de vue "mince" est un ensemble de modèles de vue qui expose vos objets de modèle directement aux vues, ce qui signifie que les vues finissent par se lier directement aux propriétés des objets de modèle. Cela peut fonctionner pour des choses comme des vues simples en lecture seule, mais que se passe-t-il si vous souhaitez avoir un comportement associé à chaque objet? Vous ne voulez pas cela dans le modèle, car le modèle n'est pas lié à l'application, il est uniquement lié à votre domaine. Vous pouvez le placer dans un objet qui enveloppe votre objet modèle et propose des données et des comportements plus conviviaux pour la liaison. Cet objet wrapper est également considéré comme un modèle de vue, et le fait de les avoir pour résultat une couche de modèle de vue "plus épaisse", où vos vues ne finissent jamais par se lier directement à quoi que ce soit sur une classe de modèle. Les collections contiennent des modèles de vue qui enveloppent les modèles au lieu de simplement contenir des modèles eux-mêmes.

Le trou du lapin va plus loin - il y a beaucoup d'idiomes à comprendre comme ValueConverters qui permettent à MVVM de fonctionner, et il y a beaucoup à appliquer lorsque vous commencez à penser à des choses comme la mélangabilité, les tests et comment transmettre des données dans votre application et vous assurer que chaque viewmodel a accès au comportement dont il a besoin (c'est là que l'injection de dépendance entre en jeu), mais nous espérons que ce qui précède est un bon début. La clé est de considérer vos visuels, votre domaine, et la structure et le comportement de votre application réelle comme trois choses différentes.

121
nlawalker

En utilisant cet article incroyablement utile comme source, voici un résumé pour Voir , ViewModel et Model .


Vue:

  • La vue est un élément visuel, tel qu'une fenêtre, une page, un contrôle utilisateur ou un modèle de données. La vue définit les contrôles contenus dans la vue ainsi que leur disposition visuelle et leur style.

  • La vue fait référence au modèle de vue via sa propriété DataContext . Les contrôles de la vue sont des données liées aux propriétés et commandes exposées par le modèle de vue.

  • La vue peut personnaliser le comportement de liaison de données entre la vue et le modèle de vue. Par exemple, la vue peut utiliser des convertisseurs de valeurs pour formater les données à afficher dans l'interface utilisateur, ou elle peut utiliser des règles de validation pour fournir une validation supplémentaire des données d'entrée à l'utilisateur.

  • La vue définit et gère le comportement visuel de l'interface utilisateur, comme les animations ou les transitions qui peuvent être déclenchées par un changement d'état dans le modèle de vue ou via l'interaction de l'utilisateur avec l'interface utilisateur.

  • Le code-behind de la vue peut définir une logique d'interface utilisateur pour implémenter un comportement visuel qui est difficile à exprimer dans XAML ou qui nécessite des références directes aux contrôles d'interface utilisateur spécifiques définis dans la vue.

REMARQUE:
.


Voir le modèle:

  • Le modèle de vue est une classe non visuelle et ne dérive d'aucune classe de base WPF ou Silverlight. Il encapsule la logique de présentation requise pour prendre en charge un cas d'utilisation ou une tâche utilisateur dans l'application. Le modèle de vue peut être testé indépendamment de la vue et du modèle.

  • Le modèle de vue ne fait généralement pas directement référence à la vue. Il implémente des propriétés et des commandes auxquelles la vue peut lier des données. Il notifie la vue de tout changement d'état via les événements de notification de changement via les interfaces INotifyPropertyChanged et INotifyCollectionChanged .

  • Le modèle de vue coordonne l'interaction de la vue avec le modèle. Il peut convertir ou manipuler des données afin qu'elles puissent être facilement consommées par la vue et peut implémenter des propriétés supplémentaires qui peuvent ne pas être présentes sur le modèle. Il peut également implémenter la validation des données via les interfaces IDataErrorInfo ou INotifyDataErrorInfo .

  • Le modèle de vue peut définir des états logiques que la vue peut représenter visuellement à l'utilisateur.

REMARQUE:
Tout ce qui est important pour le comportement logique de l'application doit entrer dans le modèle de vue. Le code pour récupérer ou manipuler les éléments de données qui doivent être affichés dans la vue via la liaison de données doit résider dans le modèle de vue.


Modèle:

  • Les classes de modèle sont des classes non visuelles qui encapsulent les données et la logique métier de l'application. Ils sont chargés de gérer les données de l'application et de garantir leur cohérence et leur validité en encapsulant les règles métier et la logique de validation des données requises.

  • Les classes de modèle ne référencent pas directement la vue ou les classes de modèle de vue et n'ont aucune dépendance sur la façon dont elles sont implémentées.

  • Les classes de modèle fournissent généralement des événements de notification de modification de propriété et de collection via les interfaces INotifyPropertyChanged et INotifyCollectionChanged. Cela leur permet d'être facilement liés aux données dans la vue. Les classes de modèle qui représentent des collections d'objets dérivent généralement de ObservableCollection<T> classe.

  • Les classes de modèle fournissent généralement la validation des données et le rapport d'erreurs via les interfaces IDataErrorInfo ou INotifyDataErrorInfo.

  • Les classes de modèle sont généralement utilisées en conjonction avec un service ou un référentiel qui encapsule l'accès aux données et la mise en cache.

20
Dom

Je l'ai écrit dans à peu près aussi "anglais simple" que je peux penser dans cette série sur MVVM . En particulier, ce diagramme est probablement l'explication la plus simple et la plus courte.

Cela étant dit, le "modèle" est essentiellement vos données ou vos règles métier. Il ne devrait vraiment pas savoir comment ni où il va être utilisé, et surtout pas quelle technologie va l'utiliser. Le "modèle" est le cœur de l'application - et il ne devrait pas avoir à se soucier de savoir si l'application est WPF, Silverlight, Windows Forms, ASP.NET, etc. - c'est juste "lui-même" sous une forme pure.

La "Vue" est la partie qui est complètement spécifique à la technologie. Dans MVVM, idéalement, la vue devrait être presque 100% XAML, car cela offre d'énormes gains de flexibilité.

Cependant, il doit y avoir quelque chose qui traduit les informations du modèle sous une forme où elles sont utilisables par la technologie à portée de main - c'est là que le ViewModel entre en jeu. Par exemple, cela "enveloppe" souvent les classes de modèle dans un "ViewModel" pour ces données spécifiques qui incluent des commandes (pour l'exécution de la logique), implémente INotifyPropertyChanged (pour la prise en charge de la liaison de données), etc. le pont qui rend le modèle utilisable par la vue.

16
Reed Copsey

Une excellente introduction à MVVM se trouve dans la vidéo de Jason Dolinger ici . J'ai gardé la vidéo avec moi pendant un bon moment au début, c'est vraiment utile.

2
Filipe Miguel

Construire un ViewModel qui présente une façade cohérente sur le modèle sous-jacent peut être beaucoup plus complexe qu'il n'y paraît. Cette article sur la construction d'objets ViewModel montre comment construire un ViewModel, et illustre certains des problèmes que vous êtes susceptible de rencontrer - ainsi que ce qui ressemble à des solutions raisonnables. Quand je l'ai lu, la section sur le traitement des collections manquait, mais elle a quand même quelques points intéressants.

0
Sprotty