Screen validation with Data Annotations in WPF

In the post Using Data Annotations to validate models I showed that it is possible to keep validations in attributes.

In this post I am going to show how to apply these validations on the client-side.

Note: All your models must implement INotifyPropertyChanged and to make it simple and clean I will be using Fody PropertyChanged nuget packaged.

In order to tell the screen it should validate the bound property we have to implement the IDataErrorInfo interface. For example:

[PropertyChanged.ImplementPropertyChanged]
public abstract class PropertyValidateModel : IDataErrorInfo
{
    // check for general model error
    public string Error { get { return null; } }

    // check for property errors
    public string this[string columnName]
    {
        get
        {
            var validationResults = new List<ValidationResult>();

            if (Validator.TryValidateProperty(
                    GetType().GetProperty(columnName).GetValue(this)
                    , new ValidationContext(this)
                      {
                          MemberName = columnName
                      }
                    , validationResults))
                return null;

            return validationResults.First().ErrorMessage;
        }
    }
}

This validation method is similar to the validation in the other post, however it validates a property instead of the whole model. With this class I can now inherit from it and my model will automatically be implementing IDataErrorInfo.

[PropertyChanged.ImplementPropertyChanged]
public class Game : PropertyValidateModel
{
    [Required]
    [StringLength(5)]
    public string Name { get; set; }

    [Required]
    [StringLength(5)]
    public string Genre { get; set; }

    [Required]
    [Range(13, 40)]
    public int MinAge { get; set; }
}

On my view I have to bind the properties with some additional settings:

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged
    , NotifyOnValidationError=True, ValidatesOnDataErrors=True}" />
  • UpdateSourceTrigger is going to tell the view to notify changes as they happen.
  • NotifyOnValidationError is going to notify when there are errors.
  • ValidatesOnDataErrors is going to enable validation.

The outcome will be:

2015-06-04 08-06-55-675

However by simply doing it this way we do not get any error messages displayed, so we do not know what is wrong with data. To display the errors we have to do a little trick with the Validation.ErrorTemplate.

The code bellow binds, through a trigger, the TextBox‘s ToolTip to the first error encountered in the control. And by setting the TextBox‘s error template we can display the error message by accessing the AdornedElement and grabbing the ToolTip where the error message is contained. If you do not want to use the ToolTip you can use the Tag property instead.

<Style TargetType="TextBox">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <Border BorderThickness="2" BorderBrush="DarkRed">
                        <StackPanel>
                            <AdornedElementPlaceholder
                                x:Name="errorControl" />
                        </StackPanel>
                    </Border>
                    <TextBlock Text="{Binding AdornedElement.ToolTip
                        , ElementName=errorControl}" Foreground="Red" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="ToolTip"
                Value="{Binding RelativeSource={RelativeSource Self}
                    , Path=(Validation.Errors)[0].ErrorContent}" />
        </Trigger>
    </Style.Triggers>
</Style>

Running the application again:

2015-13-04 08-13-57-049

Advertisements

One thought on “Screen validation with Data Annotations in WPF

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s