De bons exemples de modèle de MVVM
je travaille actuellement avec le modèle MVVM de Microsoft et je trouve le manque d'exemples détaillés frustrant. L'exemple de ContactBook inclus montre très peu de gestion de commandes et le seul autre exemple que j'ai trouvé est d'un article de magazine MSDN où les concepts sont similaires, mais utilise une approche légèrement différente et toujours pas de complexité. Y a-t-il des exemples de MVVM décents qui montrent au moins les opérations de base CRUD et le changement de dialogue/contenu?
les suggestions de tout le monde étaient vraiment utiles et je vais commencer à compiler une liste de bonnes ressources
Cadres/Templates
- WPF Model-View-ViewModel Toolkit
- MVVM Light Toolkit
- Prism
- Caliburn
- Cinch
Articles Utiles
- des Applications WPF Avec Le Modèle model-View-ViewModel Modèle de Conception
- "1519420920 de" Validation des Données .NET 3.5
- utilisation D'un modèle de vue pour fournir des Messages D'erreur de Validation significatifs
- Action fondée ViewModel et la validation du Modèle
- Dialogues
- liens de commande dans MVVM
- Plus que MVC, WPF,
- MVVM + Mediator exemple Application
Screencasts
- Jason Dolinger on Model-View-ViewModel
Bibliothèques Supplémentaires
- WPF Disciples à " l'amélioration de Médiateur Modèle de mise en œuvre (que je recommande fortement ce pour des applications plus complexes de navigation)
- MVVM Light Toolkit Messenger
9 réponses
malheureusement, il n'y a pas un seul grand MVVM exemple application qui fait tout, et il ya beaucoup d'approches différentes pour faire les choses. Tout d'abord, vous voudrez peut-être obtenir familier avec celui de l'application des cadres (Prism est un choix décent), parce qu'ils vous fournissent des outils pratiques comme l'injection de dépendance, commandant, agrégation d'événements, etc facilement essayer différents modèles qui vous conviennent.
Le prisme de presse:
http://www.codeplex.com/CompositeWPF
il comprend un très bon exemple app (le négociant en bourse) avec beaucoup de petits exemples et comment faire. Au moins, c'est une bonne démonstration de plusieurs sous-modèles courants que les gens utilisent pour faire fonctionner MVVM. Ils ont des exemples à la fois pour CRUD et dialogs, je crois.
Prism n'est pas nécessairement pour chaque projet, mais c'est une bonne chose pour se familiariser avec.
CRUD:
Cette partie est assez facile, WPF bindings rendent vraiment facile d'éditer la plupart des données. L'astuce consiste à fournir un modèle qui facilite la mise en place de L'interface utilisateur. À tout le moins, vous voulez vous assurer que votre ViewModel (ou objet d'affaires) implémente INotifyPropertyChanged
pour supporter la liaison et vous pouvez lier les propriétés directement aux contrôles de L'UI, mais vous pouvez aussi vouloir implémenter IDataErrorInfo
pour la validation. En règle générale, si vous utilisez une sorte d'une solution ORM mise en place de CRUD est un claquement.
cet article montre des opérations simples crud: http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
il est construit sur LinqToSql, mais cela n'est pas pertinent pour l'exemple - tout ce qui est important est que vos objets d'affaires implémentent INotifyPropertyChanged
(ce que les classes générées par LinqToSql font). MVVM n'est pas le but de cet exemple, mais je ne pense pas qu'il les questions dans ce cas.
cet article démontre la validation des données
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
encore une fois, la plupart des solutions ORM génèrent des classes qui implémentent déjà IDataErrorInfo
et fournissent typiquement un mécanisme pour faciliter l'ajout de règles de validation personnalisées.
la Plupart du temps, vous pouvez prendre un objet(modèle) créé par un ORM et enveloppé dans un ViewModel qui le tient et commande pour enregistrer/supprimer - et vous êtes prêt à lier L'UI directement aux propriétés du modèle.
la vue ressemblerait à quelque chose comme ceci (ViewModel a une propriété Item
qui tient le modèle, comme une classe créée dans L'ORM):
<StackPanel>
<StackPanel DataContext=Item>
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<Button Command="{Binding SaveCommand}" />
<Button Command="{Binding CancelCommand}" />
</StackPanel>
Dialogues:
Les dialogues et MVVM sont un peu délicats. Je préfère utiliser une saveur du Médiateur approche avec dialogs, vous pouvez lire un peu plus à ce sujet dans cette question StackOverflow:
WPF MVVM dialog example
mon approche habituelle, qui n'est pas tout à fait classique MVVM, peut être résumée comme suit:
une classe de base pour un ViewModel de dialogue qui expose des commandes pour les actions de propagation et d'Annulation, un événement pour faire savoir à la vue qu'une boîte de dialogue est prête à être fermée, et tout ce dont vous aurez besoin dans tous les les dialogues.
une vue générique pour votre dialogue - cela peut être une fenêtre, ou un contrôle de type de superposition" modal " personnalisé. Dans son cœur, c'est un présentateur de contenu dans lequel nous plaçons le viewmodel, et il gère le câblage pour fermer la fenêtre - par exemple, sur le changement de contexte de données, vous pouvez vérifier si le nouveau ViewModel est hérité de votre classe de base, et s'il l'est, vous abonner à l'événement de fermeture pertinent (le gestionnaire assignera le résultat du dialogue). Si vous en fournir d'autres fonctionnalité de fermeture universelle (le bouton X, Par exemple), vous devez vous assurer d'exécuter la commande de fermeture correspondante sur le modèle de vue.
quelque part vous avez besoin de fournir des modèles de données pour vos modèles de vue, ils peuvent être très simples surtout que vous avez probablement une vue pour chaque dialogue encapsulé dans un contrôle séparé. Le modèle de données par défaut pour un ViewModel ressemblerait alors à quelque chose comme ceci:
<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}>
<views:AddressEditView DataContext={Binding} />
</DataTemplate>
la vue de dialogue doit avoir accès à ceux - ci, parce que sinon il ne saura pas comment montrer le modèle de vue, en dehors de la boîte de dialogue partagée UI son contenu sont fondamentalement ceci:
<ContentControl Content={Binding} />
le modèle de données implicites établira une correspondance entre la vue et le modèle, mais qui le lance?
C'est pas si mvvm partie. Une façon de le faire est d'utiliser un événement mondial. Ce que je pense est une meilleure chose à faire est d'utiliser une configuration de type agrégateur d'événements, fournie par l'injection de dépendances - de cette façon, l'événement est mondial à un conteneur, pas l'ensemble de l'application. Prism utilise le cadre de l'unité pour la sémantique des conteneurs et l'injection de dépendances, et dans l'ensemble j'aime beaucoup L'Unité.
Habituellement, il est logique pour la fenêtre racine de s'abonner à cet événement - elle peut ouvrir la boîte de dialogue et définir son contexte de données au modèle de vue qui est passé dans avec un événement soulevé.
configurer ceci de cette façon permet à ViewModels de demander à l'application d'ouvrir un dialoguez et répondez aux actions de l'utilisateur là-bas sans rien savoir de L'UI donc pour la plupart le MVVM-ness reste complet.
Il ya des moments, cependant, où L'UI doit soulever les dialogues, ce qui peut rendre les choses un peu plus difficile. Par exemple, si la position de dialogue dépend de l'emplacement du bouton qui l'ouvre. Dans ce cas, vous devez avoir des informations spécifiques à L'interface utilisateur lorsque vous demandez l'ouverture d'une boîte de dialogue. Je crée généralement une classe séparée qui contient ViewModel et de l'INTERFACE utilisateur informations. Malheureusement, certains de couplage semble inévitable.
Pseudo code d'un gestionnaire de boutons qui soulève une boîte de dialogue qui nécessite des données de position de l'élément:
ButtonClickHandler(sender, args){
var vm = DataContext as ISomeDialogProvider; // check for null
var ui_vm = new ViewModelContainer();
// assign margin, width, or anything else that your custom dialog might require
...
ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel()
// raise the dialog show event
}
la vue de dialogue se liera aux données de position, et passera le modèle de vue contenu à l'intérieur ContentControl
. Le modèle de vue lui-même ne sait toujours rien de L'interface utilisateur.
en général je ne fais pas usage de la DialogResult
renvoie la propriété de la méthode ShowDialog()
ou s'attend à ce que le thread bloque jusqu'à la fermeture de la boîte de dialogue. Un dialogue modal non standard ne fonctionne pas toujours comme cela, et dans un environnement composite, vous ne voulez pas vraiment qu'un gestionnaire d'événements bloque de toute façon. Je préfère laisser les Modèles de vue gérer cela - le créateur d'un modèle de vue peut souscrire à ses événements pertinents, définir des méthodes commit/cancel, etc, de sorte qu'il n'est pas nécessaire de compter sur ce mécanisme D'UI.
donc à la place de ce flux:
// in code behind
var result = somedialog.ShowDialog();
if (result == ...
j'utilise:
// in view model
var vm = new SomeDialogViewModel(); // child view model
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional)
// raise dialog request event on the container
je le préfère de cette façon parce que la plupart de mes dialogues sont des commandes pseudo-modales non bloquantes et le faire de cette façon semble plus simple que de travailler autour. Facile de test de l'unité.
Jason Dolinger a fait un bon screencast de MVVM. Comme Egor l'a mentionné, il n'y a pas de bon exemple. Ils sont tous sur. La plupart sont de bons exemples de MVVM, mais pas lorsque vous abordez des questions complexes. Chacun a son propre chemin. Laurent Bugnion a aussi une bonne façon de communiquer entre les modèles. http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinch est aussi un bon exemple. Paul Stovel a un bon post qui explique beaucoup trop avec son cadre Magellan.
l'exemple de projet dans le Cinch framework montre CRUD de base et les outils de navigation. C'est un assez bon exemple d'utilisation de MVVM, et comprend un article en plusieurs parties expliquant son utilisation et ses motivations.
j'ai aussi partagé votre frustration. J'écris une demande et j'avais ces 3 conditions:
- Extensible
- WPF with MVVM
- exemples compatibles avec la GPL
Tout ce que j'ai trouvé étaient des morceaux et des morceaux, donc j'ai juste commencé à l'écrire du mieux que je pouvais. Après que je me suis mis un peu dedans, j'ai réalisé qu'il pourrait y avoir d'autres personnes (comme vous) qui pourraient utiliser une application de référence, donc je refactorisé la substance générique dans un cadre d'application WPF/MVVM et l'a publié sous la LGPL. Je l'ai appelé SoapBox Core . Si vous allez à la page de téléchargement, vous verrez qu'il est livré avec une petite application de démonstration, et le code source de cette application de démonstration est également disponible pour le téléchargement. J'espère que vous trouverez très utile. Aussi, envoyez-moi un courriel à scott {at} soapboxautomation.com si vous voulez plus d'infos.
EDIT : a également publié article Codeprojet expliquant comment cela fonctionne.
même moi j'ai partagé la frustration jusqu'à ce que je prenne l'affaire en main. J'ai commencé IncEditor.
IncEditor ( http://inceditor.codeplex.com ) est un éditeur qui tente de présenter aux développeurs WPF, MVVM & MEF. Je l'ai commencé et j'ai réussi à obtenir des fonctionnalités comme le soutien de "thème". Je ne suis pas un expert en WPF, MVVM ou MEF donc je ne peux pas y mettre beaucoup de fonctionnalité. Je vous demande sincèrement de faire en sorte que les fous aiment moi, de mieux le comprendre.
J'ajoute ici le lien d'une application WPF(Inventory Management App) qui utilise MVVM architecture conçu par moi .
son UI est génial. https://github.com/shivam01990/InventoryManagement
j'ai écrit un exemple simple MVVM à partir de zéro sur le projet de code Voici le lien MVVM WPF étape par étape . Il commence à partir d'une architecture simple à 3 couches et vous apprend à utiliser un cadre comme PRISM.