Tuesday, February 8, 2011

MVVMLight Extensions, Part: The MVVM Validation

MVVMLight is great. It is at the very least the most effective MVVM framework that is Blend / Visual Studio Design time friendly. The project focuses a lot on providing the minimum amount of built in functionality to give you the ability to make effective MVVM applications. This means that there are some areas (like validation) where MVVMLight does not add anything more that what is already available with WPF / Silverlight. So wanting to extend the library with your own extensions is a normal desire.

The Code (hosted by bitbucket)

Here is my attempt. You don't have to use it. I don't expect you to (you might want to add the code to your bag o tricks in your own mvvmlightextensions).

Here I explain what comes with the package:

A better way to add validation (Source)
The sample (kept as bare bones as possible to be simple):

We look at the model / the viewmodel and the view in turn.

Before you read about the Model and ViewModel check out snippets section. 

The Model
Its about time you move your models to object databases. With that just (2 things) :

  • Inherit from ModelBase and you neet all the goodness in the INotifyPropertyChanged and IDataErrorInfo.  

Just look at student.cs. There are two simple properties Name (string) / AdmissionDate (DateTime?) (both added with mvvminpcs snippet)

and implement:
  • override of string this[string columnname] added using mvvmde and mvvmdei snippets. Fill it up with your validation logic:

All in all about 100 keystrokes max (if you don't count the error strings :))
The ViewModel

  • Expose the Model as a property on the View (use a snippet of course):
  • Expose your commands (again use a snippet):

  • IMPORTANT Use base.UIValidataionErrorCount and ModelObject.Error.Count to determine if there are any errors (e.g return base.UIValidationErrorCount == 0 && this.Student.Errors.Count == 0 is used in the sample to determine if the save command can execute)

The View
Nothing much to do except that
  • inherit from ViewBase rather than UserControl:

  • Define a style for validation template and apply it in your View Xaml:
            <!--Create a validataion control template for a TextBlock-->
            <ControlTemplate x:Key="validationTemplate">
                    <TextBlock Margin="5,0,5,0" Foreground="Red" FontSize="16" VerticalAlignment="Center" Text="*" ToolTip="{Binding ElementName=errorAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
                    <AdornedElementPlaceholder x:Name="errorAdorner" />
            <!--Set the Validation Error Template to the control template we just created-->
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource validationTemplate}" />
  • And in all the bindings that are bound to the Model (view the ViewModel) add the following:
    NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True

That wasn't so hard was it.