2010-11-30 14 views
0

Une approche commune MVVM/WPF consiste à lier les contrôles de l'interface utilisateur directement à l'objet de modèle sous-jacent. L'objet de modèle peut contenir sa propre logique de validation (peut-être exposée via IDataErrorInfo) ou peut être validée par une classe d'assistance vérifiant la présence d'erreurs dans une instance d'objet de modèle. Dans les deux cas, le modèle contient parfois des données non valides et se trouve donc dans un état non valide. Toutefois, dans le monde DDD, le modèle ne doit jamais être dans un état non valide. Comment proposez-vous la validation lors de l'utilisation de WPF et DDD?Validation lors de l'utilisation de MVVM (WPF) avec un modèle basé sur DDD

Merci,
Ben

+0

Où DDD dit se lier directement au modèle dans MVVM ?? – Aliostad

+1

Si vous vous liez directement au modèle, ne pouvez-vous pas simplement utiliser ValidationRules (ou même simplement ValueConverters) pour empêcher les liaisons de relayer des données invalides vers le modèle? – Moonshield

Répondre

1

J'ai tendance à penser qu'une façade ou une couche similaire devrait être utilisée comme "modèle" MVVM. Cette façade peut être dans un état invalide (contrairement au modèle DDD). Pour la validation, il peut soit contenir sa propre logique ou un outil comme FluentValidation peut être utilisé. Une fois qu'il est dans un état valide, sa fonction "action" peut être appelée. Cela transmettra les données de la façade au modèle DDD sous-jacent. Avec cette approche, à aucun moment le modèle DDD ne rencontre des données invalides. Avec cette approche, la façade et sa logique de validation peuvent être utilisées par plusieurs paires de modèles vue/vue, éliminant la duplication logique de validation présente lorsque chaque modèle de vue effectue sa propre validation.

1

Je ne pense pas que la vue en MVVM devrait lier directement au modèle de domaine, il devrait vraiment se lier à un modèle Voir à la place. Alors le modèle de vue peut être dans un état "invalide" qui peut être reflété par IDataErrorInfo. Plus tard, lorsqu'une opération utilisateur (par exemple, Enregistrer, OK, Appliquer) applique ce modèle au modèle de domaine sous-jacent si le modèle de domaine applique la validité, vous pouvez également empêcher l'application en n'autorisant pas l'opération dans l'interface utilisateur.

Bien que je dois dire que j'ai trouvé que ce n'est pas toujours facile de le faire sans dupliquer la logique de validation dans une certaine mesure. La validation appartient à votre logique applicative (modèle de domaine).

+1

Votre dernier paragraphe mentionne l'inconvénient qui m'amène à m'éloigner de cette approche: le fait que la logique de validation devienne spécifique à la VM et tend à se retrouver dupliquée dans chaque VM qui interagit avec le même modèle sous-jacent. –

0

Je suggère de jeter un oeil à FluentValidation pour .NET.

J'ai en fait eu de la chance car le setter ViewModel appelait l'objet Model sous-jacent et permettait à FluentValidation de lancer une exception. Si vous utilisez une zone de texte WPF, la liaison continuera de fonctionner, mais la zone de texte affichera un contour rouge (en supposant que vous avez utilisé la syntaxe où TextBox met à jour le ViewModel à chaque frappe). Ne lancez pas une exception dans le getter sinon vous casserez la liaison. Il est préférable de router toute votre communication de ViewModel vers le Model via un intermédiaire (j'ai introduit un Presenter, mais cela peut être aussi simple que de passer l'opération Model en tant que lambda à un callback sur un médiateur). Lorsqu'une exception se produit lors de l'utilisation du modèle, le présentateur intercepte l'exception et affiche un message convivial à l'attention de l'utilisateur avec les détails de l'exception. FluentValidation produit de très bons messages d'erreur par défaut à cette fin.

+0

J'ai juste essayé de lier une propriété et de lancer une exception dans le setter. Il ne s'affiche pas comme un échec de validation. Utilisez-vous une bibliothèque pour cela? –

+1

@Andy Lowry: Dans la liaison, vous devez ajouter ExceptionValidationRule à Binding.ValidationRules.Je n'ai pas besoin de les spécifier, mais il est intéressant de noter que j'utilise 'UpdateSourceTrigger = Explicit' et appelle' UpdateSource() 'sur BindingExpression. –