Thursday Night

Paul Betts’s personal website / blog / what-have-you

WPF Data Validation using DataAnnotations

Data Validation in WPF isn’t that great

As part of trying to put together a “base application” for starting projects at work, I’ve had a look at WPF Data Validation for the first time. Compared to ASP.NET MVC, WPF’s data validation is really primitive – it basically leaves you to do everything by hand. Fortunately, the DataAnnotations DLL is sufficiently decoupled, that we can actually use it – props to Brad Wilson’s Data Annotations article for the inspiration to add it to WPF.

Disclaimer: The DataAnnotation guys would probably tell me I’m Doing It Wrong(r) here, and this code is proof-of-concept and very inefficient. However, it’ll gets the idea across

Using DataAnnotations

First, we’ll make a dummy class:

public class PersonEntry : DataValidable
{
    [StringLength(35, MinimumLength = 3)]
    public string Name {get; set;}

    [StringLength(10, MinimumLength = 10)]
    public string PhoneNumber {get; set;}
}

public class DataValidatable : IDataErrorInfo
{
    public class Foo : IDataErrorInfo
    {
        public string Error{
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName] {
            get { throw new NotImplementedException(); }
        }
    }
}

Now, let’s implement IDataErrorInfo using data annotations:

public string this[string columnName]
{
    get {
        var prop = GetType().GetProperty(columnName);
        var validationMap = prop
            .GetCustomAttributes(typeof(ValidationAttribute, true)
            .Cast<validationattribute>();

        foreach(var v in validationMap) {
            try {
                v.Validate(prop.GetValue(this, null), columnName);
            } catch (Exception ex) {
                return ve.Message;
            }
        }

        return null;
    }
}
</validationattribute>

Making it show up in the view:

To actually see your validations get called, you need some magic words in the binding – here’s how to do it:

Text="{Binding Person.Name, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnDataErrors=true}"

Written by Paul Betts

April 27th, 2010 at 10:16 pm