Monday, 29 July 2013

Notifying the user of validation errors using Prism for the Windows Runtime

Previously I’ve blogged about how to create a model class with validation support by using Prism for the Windows Runtime. This was achieved by deriving the model class from Prism’s ValidatableBindableBase class.

In this blog post I’ll demonstrate how to hook up the model class to code that will allow the user to input text, perform the validation, and notify the user of any validation errors in the input.

Implementation

The MainPageViewModel class creates an instance of the Person model class and allows its data to be validated.

public class MainPageViewModel : ViewModel
{
    private Person _person;
 
    public DelegateCommand ValidateCommand { get; private set; }
    public Person Person
    {
        get { return _person; }
        set { SetProperty(ref _person, value); }
    }
 
    public MainPageViewModel()
        : this(new Person())
    {
    }
 
    public MainPageViewModel(Person person)
    {
        _person = person;
        ValidateCommand = new DelegateCommand(Validate);
    }
 
    private void Validate()
    {
        _person.ValidateProperties();
    }
}

The TextBox on the MainPage binds to the instance of the Person model class through the Person property. This instance is created when the MainPageViewModel is constructed. The Button on the MainPage binds to the ValidateCommand. When the ValidateCommand is invoked the Validate method is called.

Triggering validation explicitly

I’ve previously explained how validation can be triggered automatically when property values change. In addition, validation can also be triggered explicitly by calling the ValidatableBindableBase.ValidateProperties method, which in turn calls the BindableValidator.ValidateProperties method. This is accomplished by the Validate method in the MainPageViewModel class. For an explanation of how the BindableValidator.ValidateProperties method works see Validating user input in AdventureWorks shopper.

Highlighting validation errors

In this sample app validation errors are shown to the user by highlighting the TextBox control that contains invalid data, and by displaying an error message beneath the control.

image

image

The HighlightOnErrors attached behaviour is used to highlight the TextBox control when a validation error occurs. The behaviour is attached to the TextBox control that is used for user input.

<TextBox behaviours:HighlightOnErrors.PropertyErrors="{Binding Person.Errors[Name]}"
         Grid.Column="1"
         Grid.Row="2"
         Text="{Binding Person.Name, Mode=TwoWay}" />

The attached behaviour gets and sets the PropertyErrors dependency property, which is defined in the HighlightOnErrors class.

public static DependencyProperty PropertyErrorsProperty =
    DependencyProperty.RegisterAttached("PropertyErrors", typeof(ReadOnlyCollection<string>), typeof(HighlightOnErrors),
    new PropertyMetadata(BindableValidator.EmptyErrorsCollection, OnPropertyErrorsChanged));

The PropertyErrors dependency property is registered as a ReadOnlyCollection of strings, by the RegisterAttached method. When the value of the PropertyErrors dependency property changes, the OnPropertyErrorsChanged method is invoked to change the highlighting style of the TextBox.

private static void OnPropertyErrorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
    if (args == null || args.NewValue == null)
    {
        return;
    }
 
    TextBox textBox = (TextBox)d;
    var propertyErrors = (ReadOnlyCollection<string>)args.NewValue;
    Style textBoxStyle = (propertyErrors.Count() > 0) ? (Style)Application.Current.Resources["HighlightTextStyle"] : null;
    textBox.Style = textBoxStyle;
}

The OnPropertyErrorsChanged method gets the instance of the TextBox that the PropertyErrors dependency property is attached to, and gets any validation errors for the TextBox. If validation errors are present the HighlightTextStyle is applied to the TextBox, so that it is highlighted with a red BorderBrush.

Finally, the UI displays the validation error message in a TextBlock below the TextBox control.

<TextBlock Grid.Column="1"
           Grid.Row="3"
           Style="{StaticResource ErrorMessageStyle}"
           Text="{Binding Person.Errors[Name], Converter={StaticResource FirstErrorConverter}}" />

The TextBlock binds to the Errors property of the Person object. The Errors property is provided by Prism’s ValidatableBindableBase class, and is an instance of the BindableValidator class. The indexer of the BindableValidator class returns a ReadOnlyCollection of error strings, with the FirstErrorConverter retrieving the first error from the collection, for display.

Summary

In this blog post I’ve demonstrated how to use Prism for the Windows Runtime to validate user input, and notify the user of any validation errors. The ValidatableBindableBase.ValidateProperties method performs validation, with the HighlightOnErrors attached behaviour highlighting the control that contains the validation error. Validation error text can be retrieved from the Errors property of the model object, which is provided by Prism’s ValidatableBindableBase class.

The sample app can be downloaded here.

No comments:

Post a comment