MVVM – Validation

I have never, ever sought validation from the arbiters of British poetic taste
Linton Kwesi Johnson

In this post I’m going to look at how to validate user-entered data in a WPF / MVVM application. The context is that the user will be presented with a Model instance to edit, and will not allowed to proceed until all the validation rules for that Model type are passing. In line with this blog series, I’ll be aiming to do that in a structured manner, with as little duplicated code as possible

Validation within WPF / MVVM is provided by the IDataErrorInfo interface, which has just two members …

    public interface IDataErrorInfo
        string this[string propertyName] { get; }
        string Error { get; }

This interface has actually been available in .net since version 1.1 – long before WPF was created – and it turns out that in WPF the Error property is redundant. So can one simple indexed property provide all that is is required for validation? Well it’s not quite the whole story, but it certainly is an important part of the process.

Validation through IDataErrorInfo

IDataError info needs to be implemented on whatever the specific control is actually bound to. This could be the Model itself, or if required on the ViewModel (which will indirectly set a corresponding property on the Model). An example of this latter case is PersonViewModel.DepartmentVm in the demo StaffManager application. Continuing with out D.R.Y. theme, this duel use suggests that the behaviour should be defined in a common base class for both Model and ViewModel classes. perObservableObject implements IDataErrorInfo, along with a virtual method for validating individual properties and an IsValid property for the whole class.

Due to our use of PropertyChanged.Fody in Model classes – there are no concrete property setters where linked properties can automatically be re-validated. To get around this, the base class for Models – perModelBase, includes AddPropertyDependency() which is used to define a link between two properties. Each time the source property is updated, the PropertyChanged event will be invoked for the dependent property, which in turns refreshes the validation.

Validation in DataBinding

So having created a method for validating properties in a Model or ViewModel class, how do we go about actually calling it? The second step of the validation process is in the data binding. Set the ValidatesOnDataErrors property of the Binding declaration to True. For example …

    <TextBox Text="{Binding Model.Name, 
                            ValidatesOnDataErrors=True }" />

Now, each time the bound property is updated (after each key-stroke in this case due to UpdateSourceTrigger= PropertyChanged), the validation Item[] property will be evaluated with the bound property name as the input parameter.

Displaying Validation Results

An additional bonus of using IDataErrorInfo, is that a WPF control whose data binding has failed validation will indicate this state by drawing a red border around itself, without us having to do any extra work. The last part of this post will demonstrate a way to improve this aspect of the user-interface.

The display of error information for a control is defined by its Validation.ErrorTemplateProperty – another example of an attached property. This control template is used to define additional UI elements, that are drawn on the adorner layer of the form, around the control that it is attached to, whenever its data bound property fails validation. This is where the default red border comes from. Within an error template, AdornedElementPlaceholder is a placeholder for the control that the template is attached to – AdornedElement is the actual control.

It would be nice to have a common styling and behaviour, including displaying errors, that can be applied to any WPF control – without having to write new control templates for each type. perControlHost meets just that need – it is used as a visual wrapper around any existing control definition, offering a coloured background / border and a text caption. The default validation template for perControlHost is slightly more complicated than the WPF default …

    <ControlTemplate x:Key="ControlHostDefaultValidationErrorTemplate">
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />

            <AdornedElementPlaceholder Grid.Column="0"
                                       VerticalAlignment="Center" />

            <Path Grid.Column="1"
                  Data="M 0,0 M 200,200 M 150, 186 L 50, 14 M 200, 100 L 0, 100  M 150, 14 L 50, 186"
                  UseLayoutRounding="True" />

The visible element of this template is a red asterisk on the right edge of the control, to indicate the error state.

The second half of the UI for validation is a tooltip on the control host to display the text of the error message. One key point to note is how the tooltip gets its text content. Because tooltips exist outside of the standard visual tree, they can’t reference another control by name. All that a tooltip knows about is its own PlacementTarget – the UIElement that it is displayed against, in this case the border. To allow the tooltip to access the wrapper’s content, I’ve hijacked the (otherwise unused) Tag property of the border to pass this in. The parentheses in the data trigger binding are required because Validation.HasErrors is an attached property.

The demo project for this post shows the full validation process in action, including dependent property validation, and how perControlHost.ValidationErrorTemplate can be used to define an alternative template for a specific instance.

As usual the code samples for this blog are available on Github, along with my own personal C# / WPF library.

One thought on “MVVM – Validation

  • 15th February 2018 at 15:08

    I certainly hope you will continue this mvvm series. Very good info indeed!


Leave a Reply

Your email address will not be published. Required fields are marked *