Forwarding the Result of WPF Validation in MVVM
A question that is frequently raised in connection with MVVM design is how one can access the result of WPF Validation (Validation.HasError) from the ViewModel. There is a way, but before I start explaining it, I’d like to ask an important question:
Why Would You Want to Do it?
Normally you would say: actually the ViewModel is responsible for validating the user input. So, if the input is invalid, the ViewModel should already know about it, isn’t it? Well, partially. There are some cases were the user input never reaches the ViewModel: when what the user entered cannot be converted to the correct data type, e.g. with date values or numbers. Catching these conversion errors in the ViewModel requires that you wrap each and every property of the data model that has one of these data types into a ViewModel property of type string, which bloats the ViewModel unnecessarily, and creates exactly the kind of glue code one tries to avoid by using the MVVM pattern in the first place.
One possibility to work around this is to create general, reusable ValidationRules for type checking and assign them to the Bindings. But then the ViewModel would have to know about the results of these checks in order to disable or enable commands or make other decisions based on the validity of its data. This would be the use case for the following technique:
How to Do it
The trick is to create a Sticky Property (which is a special case of an attached property) which, different from Validation.HasError, allows data bindings with direction to the source:
In the metadata of this property, I set a flag that tells WPF that this property expects to forward its value to the source, so we don’t have to set the Binding Mode on the bindings in XAML.
In order to reflect the value of Validation.HasError, we need to set up an event that fires whenever the value of this property changes. In order to find out that we need this event, the CoerceValue callback of the property checks whether the property is data bound:
And that’s it… Notice that the CoerceValue callback uses a private DependencyProperty in order to store the DependencyPropertyDescriptor that is used to set up the change event. This has two purposes: it allows to remove the notification conveniently, and more important, it serves as a flag in order to see whether the notification is already in place or still needs to be set up.
You can download an example for this technique here. (You will have to change the extension to .zip in order to extract the contents).
I found the information about how to monitor changes in any object’s DependencyProperties in this article by Charles Petzold.