A while ago, WPF guru Josh Smith blogged about using the ViewModel to provide a first line of defence when validating data using the MVVM model. In his article, Josh talks about having the ViewModel perform some validation before passing this back to the underlying model. In his example, he uses a string property to perform initial validation on a UI element before it updates an integer, so that the user can type in abc123, but the model only gets updated if it’s a valid number. Please read his article here for more information.
While I liked Josh’s implementation, there was something nagging at me – his implementation relied heavily on switch statements in the property validation, and this really goes against the grain for me. Thinking about this for a while, it seemed to me that we could achieve a similar implementation and, at the same time, provide a nice level of abstraction. To do this, we can use the Action<T> delegate to nicely decouple the validation from the actual property validation. The following class provides the underlying mechanism for separating the validation.
Now, both the ViewModel and Model classes can derive from this class and get access to the same functionality. The following class demonstrates this:
The interesting bit of this class is how simple the implementation of IDataErrorInfo here actually is. All the “magic” has been taken care of by creating an Action that will invoke the ValidateAge method. By calling AddValidation on the base class and passing the name of the property that the validation applies to, we can automatically hook up to perform the validation.
You can download the sample project here. Be sure to change the extension back from Doc to Zip and then decompress it.
Nice post Pete
Thanks Sacha.
Why don’t you move the validation to the base class, so that all classes get it?
No need to pass instance when it’s not a static method so you’ll have this anyway.
Steve – the next stage of this is to move the validation out altogether. In a future update, I’ll demonstrate using IoC to decouple the validation altogether.
Pete, just seen your comment on separating validation implementation from the model. Have you looked at using a validation framework such as ValidationAspects. You can register validation against the model’s properties separate from the model implementation.
I recently blogged about WPF validation at http://thetreeknowseverything.net/2009/01/21/domain-model-validation-wpf/ which might be of interest to you.
Thanks for that Mike. I’ll have a read of your blog to get more information about this – sounds good to me.
Mike, now that I’ve had a chance to read your article it seems to me like we’re looking at tackling two different problems. In the case of an Aspects framework, the validation is known up front and not subject to change. What I’m going to be looking at is the ability to add new rules “on the fly” without having to recompile the application. We do have applications where this would be useful.
No, you can replace/augment validation at runtime programmatically or by configuration. You’re not limited to attributes – they’re really only of use for coding-contracts or simple business rules validation. For more complex validation you’d probably want to register lambda functions on Types, Properties or Method Parameters. There’s a more detailed summary of features here http://thetreeknowseverything.net/2009/01/09/introducing-validation-aspects/
Cool. I hadn’t found this information, but that’s really interesting. Thanks for the heads up Mike.
Interresting approach Pete, thanks for sharing that. But it feels quite strange to specify the validation rules twice, first in the entity business rules and second in the viewmodel.
I use a much simpler approach, with a very simple validation engine that uses predicates as rule methods:
BusinessRules.Register(x => x.FirstName).IsNotNullOrEmpty();
BusinessRules.Register(x => x.Age).IsGreaterThanOrEqualTo(18);
BusinessRules.Register(x => x.Age).IsLessThan(100);
Each validation method is actually an extension method that wraps the appropriate validation predicate:
public static IBusinessRule IsGreaterThan(this IBusinessRule businessRule, V comparisonValue) where V : IComparable {
businessRule.Predicate = x => x.CompareTo(comparisonValue) > 0;
businessRule.ErrorMessage = string.Format(ValidationErrors.IsGreaterThan, businessRule.Name, comparisonValue);
return businessRule;
}
Furthermore, in the entity property setters i use a SetProperty function which handles the illegal input.
Thanks for the comments Dave – to answer the unspoken question about the validation rules, they aren’t specified twice – they are different rules doing different things. The ViewModel validation is the first stop to ensure that we don’t try to pass a string into the age field in a model itself. In a future issue of the code, I’m going to show how to bind the CanExecute of a command into this to see whether or not an item can be saved based on the validation.
Very elegant!
Thanks Josh – I’m glad you like it.
I am just about to write a small validation engine for my current project and I was thinking along the same lines as this. I love how you can so easily hook it up to IDataErrorInfo while still maintaining a nice structure in the background.
Actually I think what Dave is outlining looks very interesting too. However I can’t really grasp the full idea of it. Sorry for hogging your blog Pete, but Dave I would love to see some more of your idea. If you don’t wanna publish more here, feel free to contact me by email at tomas at specopssoft dot com.
Tomas – I’ve no problem with you “hogging the blog”;->. Dave’s approach is amazing, and I’m looking more into it myself. As for hooking into IDataErrorInfo while maintaining structure – this is a real question of programming style; I feel that switch statements are way overused and there are fantastic mechanisms and techniques that can be used to circumvent them.
Thanks for your comments.
Tomas, my approach is not that different from Pete’s; it’s just that I use generic predicates as validators as opposite to Pete’s generic actions. Instead of creating a specific function (or class) for each validator, I use some extension methods which can be then reused in various projects. Indeed using lambda-based predicates gives you that flexibility I always missed in .NET
I will try to find some time later tonight, to create a proper post about it and attach also a small example.
Dave
Dave – did you get a chance to put a simple example together? I’m interested in seeing a bit more of this as well as Tomas.
Very nice! I just changed what I was doing with your approach and like it so much more now. Thanks for the great post and elegant solution.
Robert – I’m glad you like it. It just seems so much neater to me.
Pete, I’m using the DataGrid. Therefore, I must use the DataGrid.RowValidationRules, wich works with an seperate class, wich does not have a reference to the ViewModel (I can’t find out, how to determine the VievModel in this class).
Have you any idea, how to handle the DataGrid in an ViewModel-based validation?
For anyone arriving here ‘late’ (like me), Mike Saunders blog has moved, and the two quoted posts are here: http://thetreeknowseverything.wordpress.com/2009/01/09/introducing-validation-aspects/ and here: http://thetreeknowseverything.wordpress.com/2009/01/21/domain-model-validation-wpf/
Pingback: How to: Good examples of MVVM Template | SevenNet
Pingback: Good examples of MVVM Template - TecHub