2010-11-30 4 views
0

Ein gängiger MVVM/WPF-Ansatz besteht darin, die Steuerelemente der Benutzeroberfläche direkt an das zugrunde liegende Modellobjekt zu binden. Das Modellobjekt kann eine eigene Validierungslogik enthalten (möglicherweise über IDataErrorInfo verfügbar gemacht) oder kann von einer Hilfsklasse überprüft werden, um eine Modellobjektinstanz auf Fehler zu überprüfen. In beiden Fällen hat das Modell zeitweise ungültige Daten und befindet sich daher in einem ungültigen Zustand.Validierung bei Verwendung von MVVM (WPF) mit einem DDD-basierten Modell

In der DDD-Welt ist das Modell jedoch nie in einem ungültigen Zustand. Wie empfehlen Sie die Validierung bei der Verwendung von WPF und DDD?

Danke,
Ben

+0

Wo in DDD sagt binden direkt an das Modell in MVVM? – Aliostad

+1

Wenn Sie direkt an das Modell binden, können Sie nicht einfach ValidationRules (oder auch nur ValueConverter) verwenden, um zu verhindern, dass Bindungen ungültige Daten an das Modell weiterleiten? – Moonshield

Antwort

1

Ich denke, dass eine Fassade oder eine ähnliche Schicht als MVVM "Modell" verwendet werden sollte. Diese Fassade kann sich im Gegensatz zum DDD-Modell in einem ungültigen Zustand befinden. Zur Validierung kann entweder eine eigene Logik oder ein Tool wie FluentValidation verwendet werden. Sobald es sich in einem gültigen Zustand befindet, kann seine "do action" -Funktion aufgerufen werden. Dadurch werden die Daten in der Fassade an das zugrunde liegende DDD-Modell übergeben. Bei diesem Ansatz trifft das DDD-Modell zu keinem Zeitpunkt auf ungültige Daten. Mit diesem Ansatz können die Fassade und ihre Validierungslogik von mehreren Ansicht/Ansicht-Modellpaaren verwendet werden, wodurch die Duplizierung der Validierungslogik vermieden wird, wenn jedes Ansichtsmodell seine eigene Validierung durchführt.

1

Ich glaube nicht, dass die Ansicht in MVVM sollte direkt mit dem Domänenmodell verbindlich, es sollte wirklich statt zu einem View-Modell verbindlich. Dann kann das Ansichtsmodell in einem "ungültigen" Zustand sein, der durch IDataErrorInfo reflektiert werden kann. Erst später, wenn eine Benutzeroperation (z. B. Speichern, OK, Anwenden) diese auf das zugrunde liegende Domänenmodell anwendet, sollte das Domänenmodell die Gültigkeit erzwingen. Sie können die Anwendung auch verhindern, indem Sie die Operation in der Benutzeroberfläche nicht zulassen.

Obwohl ich sagen muss, ich habe festgestellt, dass es nicht immer einfach ist, dies zu tun, ohne die Validierungslogik zu einem gewissen Grad zu duplizieren.

+1

Ihr letzter Absatz erwähnt die Nachteile, die mich von diesem Ansatz wegführen - die Tatsache, dass die Validierungslogik VM-spezifisch wird und dazu tendiert, in jeder VM, die mit demselben zugrunde liegenden Modell interagiert, zu duplizieren. –

0

Validierung gehört in Ihre Geschäftslogik (Domänenmodell). Ich schlage vor, einen Blick auf FluentValidation für .NET zu werfen.

Ich hatte tatsächlich Glück, dass der ViewModel-Setter das zugrunde liegende Model-Objekt aufruft und FluentValidation eine Ausnahme auslöst. Wenn Sie eine WPF-TextBox verwenden, funktioniert die Bindung weiterhin, aber die TextBox zeigt eine rote Umrandung (vorausgesetzt, Sie haben die Syntax verwendet, bei der die TextBox das ViewModel bei jedem Tastendruck aktualisiert). Werfen Sie keine Ausnahme in den Getter, sonst brechen Sie die Bindung.

Es ist besser, alle Ihre Kommunikation vom ViewModel zum Model über einen Vermittler zu leiten (ich habe einen Presenter eingeführt, aber das kann so einfach sein wie die Übergabe der Model-Operation als Lambda an einen Callback auf einem Mediator). Wenn beim Ausführen des Modells eine Ausnahme auftritt, fängt der Presenter die Ausnahme ab und zeigt dem Benutzer eine entsprechende Nachricht mit den Details der Ausnahme an. FluentValidation erzeugt zu diesem Zweck wirklich schöne Standardfehlermeldungen.

+0

Ich habe gerade versucht, an eine Eigenschaft zu binden und eine Ausnahme im Setter zu werfen. Es wird nicht als Validierungsfehler angezeigt. Verwenden Sie eine Bibliothek, um dies zu tun? –

+1

@Andy Lowry: In der Bindung müssen Sie Binding.ValidationRules ExceptionValidationRule hinzufügen.Ich muss diese nicht angeben, aber es ist erwähnenswert, dass ich 'UpdateSourceTrigger = Explicit' verwende und' UpdateSource() 'auf BindingExpression rufe. –