Home > WPF, XAML > Using Custom Validation Rules in WPF

Using Custom Validation Rules in WPF

October 13, 2009

Anyone who has ever developed data driven applications of any sort has had to deal with validation.  Let’s face it, users make mistakes, even if they are developers!  Validation can be a real pain to implement, and contrary to all our HelloWorld style applications, MessageBox.Show is not the best way to inform our users that we have an issue with their keyboarding skills.

I remember being ecstatic when I learned about the WinForms ErrorProvider. This handy little approach finally gave us a nice way to alert the user of the problem without being too heavy handed in the UI.  Where it failed, though, was in customization.  First of all, it took a lot of code behind to manage the ErrorProvider: checking field values against business rules, updating the provider’s list of errors, or clearing it out when the status was OK ended up being a lot of code, especially when there were a lot of data fields. And then, beyond deciding whether or not the Error symbol would blink (I always hated the blinking exclamation point), there wasn’t a lot of pizzazz we could add.  Of course, that’s all changed with WPF.

Getting Started

Before I go any further, you can find most of the basics in these articles:

I recommend reading these articles. The CodeProject article even links to a Project with a WPF version of ErrorProvider.  I will be using a couple code samples from these articles.

I’m not going to harp too much on the details presented in these other articles.  Instead, I’m going to layout what I did to get this working and hopefully give you enough information to get started.

Using IDataErrorInfo

When you first start looking into validating data in WPF you will no doubt run into IDataErrorInfo.  This seems to be the jumping off point.  Implementing the interface is pretty straightforward.  Here is a typical example:

using System.ComponentModel;
namespace ValidationRulesPlay.ViewModels
    public class DataErrorInfoSample : ViewModelBase, IDataErrorInfo
        private int _int1;
        private int _int2;

        public int Int1
            get { return _int1; }
            set { _int1 = value; FirePropertyChangedEvent("Int1"); }

        public int Int2
            get { return _int2; }
            set { _int2 = value; FirePropertyChangedEvent("Int2"); }

        #region IDataErrorInfo Members

        public string Error
            get { return null; }

        public string this[string columnName]
                string result = null;

                switch (columnName)
                    case "Int1":
                        if (Int1 > 9999999)
                            result = "Int1 number cannot be greater than 9999999.";

                    case "Int2":
                        if (Int2 > 99)
                            result = "Int2 number cannot be greater than 99.";


                return result;



[NOTE: the class above inherits from ViewModelBase, a class I use to implement INotifyPropertyChanged.]

And then you add a piece to your Binding syntax in XAML to activate it:


This works and will by default wrap the offending textbox with a red border.  It’s not a bad experience for simple examples, but as I see it there are a couple of drawbacks.

First, IDataErrorInfo validated the data after the property has been set. So if I type in a value that is out of range, the target property is still invalidly set with the bad value.  This means that I have to do extra work to correct the error.  In other words, this approach lets me put bad data in that I must then take out.  Wouldn’t it be better if it just didn’t go in in the first place?  Second, this interface uses a custom indexer, which frankly just feels like magic.  It’s a personal preference, and a fear of the unknown, but I just don’t like it.

My other real issue with it is that it ends up being a lot of repetitive code.  Look at the example above and you’ll see two integer values that are both tested to be within a certain range.  While the ranges are different, the action is the same.  Of course, you could create a method, or better yet an Extension Method, to handle this situation.  Maybe it’s because of the hard-coded nature of the validation messages, but it still doesn’t feel right to me.

Creating Custom Validation Rules

Wouldn’t it be better to have a reusable piece of code to handle these similar situations?  One with no real hard coding?  In .NET 3.5 SP1 we have just such an animal, the Custom Validation Rule.

ValidationRule is an abstract class that we can inherit from to create a custom validation rule class of our own.  I could certainly create a custom rule class for each property in my DAL, and perhaps sometimes a custom class for a particular field would make sense, but many times all I need is a generalized validation rule. 

I mentioned previously that IDataErrorInfo checks the validation after the property has been updated.  This means if we attempt to insert a non-integer field with a non-integer value, the validity checking never occurs: instead, WPF swallows the error.  Using a validation rule causes the validation to occur before the property is updated, so we can easily prevent such an occurrence and report it to the user.  It does still allow the bad data into the TextBox, but that’s not necessarily a bad thing.

For this example, we need a validation rule that will report when the user attempts to insert a non-integer character.  We also want to be able to specify a range of acceptable values.  Additionally, we are going to add a few fields to help customize the messaging experience.  Here is the complete class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;

namespace CustomValidationRules
    public class IntegerValidationRule : ValidationRule
        private int _min = int.MinValue;
        private int _max = int.MaxValue;
        private string _fieldName = "Field";
        private string _customMessage = String.Empty;

        public int Min
            get { return _min; }
            set { _min = value; }

        public int Max
            get { return _max; }
            set { _max = value; }

        public string FieldName
            get { return _fieldName; }
            set { _fieldName = value; }

        public string CustomMessage
            get { return _customMessage; }
            set { _customMessage = value; }

        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
            int num = 0;

            if (!int.TryParse(value.ToString(), out num))
                return new ValidationResult(false, String.Format("{0} must contain an integer value.", FieldName));

            if (num < Min || num > Max)
                if (!String.IsNullOrEmpty(CustomMessage))
                    return new ValidationResult(false, CustomMessage);

                return new ValidationResult(false, String.Format("{0} must be between {1} and {2}.",
                                           FieldName, Min, Max));

            return new ValidationResult(true, null);

The magic all happens in the overridden Validate method.  There are lots of additional ways you could customize this, but there should be enough in this example to get you started writing your own custom validation rules.

I put generalized rules like this in a separate project and namespace so I can reuse them in many projects.  For rules that are specific to a particular DAL or Application you can just as easily put them in those namespaces.

Consuming Custom Validation Rules

Now that we have an IntegerValidationRule class, let’s add it to our XAML so we can put it into action.  Unfortunately, there is no facility in Blend for doing so, so we’ll have to edit the XAML directly.  The first thing to do is add a namespace reference to the XAML pointing to the location of the custom validation rules.

We are going to add the validation to a TextBox.  Normally, I would use the shortened syntax to specify a binding, but in this case I’m going to use long hand because there is a lot of detail to add. Here is the completed sample:

    Validation.ErrorTemplate="{StaticResource validationTemplate}"
    Style="{StaticResource textBoxInError}"
                FieldName="Int1" />

There are a number of things going on here.  First, notice we added the Validation.ErrorTemplate property.  This specifies a template to use when the error condition exists.  I’ll cover that shortly along with the Style property. Both of these are used to customize the display of the error condition.

Next, in the TextBox.Text property we’ve added a long hand version of Binding.  I use UpdateSourceTrigger to cue the validation check whenever the property changes.  If I use the default value the change will only occur once the element loses focus, and I prefer a more real time effect.

Within the Binding property, we’ve added a subproperty section called Binding.ValidationRules.  Inside this property we add references to the rules we wish to implement. This will create an instance of the custom validation rule with the specified property values.  Since I set default values in the class, I can leave off any property and the validation will still function. As you can see in the example above, this is where I can set the property values for this particular instance of my IntegerValidationRule.  In this case we are allowing the integer range to be between 1 and 9999999, and specifying the name we want the message to associate with any error.

That’s all we need to do to consume the custom rule.  Now we’ll take a look at the ControlTemplate and Style to see how we can control the display.

Styling a Custom Validation

I took both the ControlTemplate and the Style from the MSDN article How To Implement Binding Validation.  Here are the original values:

                Text="!" />
        <AdornedElementPlaceholder />
    TargetType="{x:Type TextBox}">
                Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />

Insert these into the Windows.Resources section of the XAML.  If you’ve been coding along, you can run the sample now and it will work.  The only thing you really get is a red exclamation point to the left of the TextBox and a Tooltip if you hover over it.  This is OK, but I didn’t really feel it was enough to grab the user’s attention, so I’m going to change it just a little.

Before I do that, though, take a look at the ControlTemplate: there is something interesting here called an AdornedElementPlaceholder.  This nifty little element allows us to wrap the original ControlTemplate with additional elements.  In this sample, we are placing a TextBlock with the exclamation point just in front of our original control.  Feel free to experiment with this and add some code of your own around the offending TextBox.

Back to the Style: I want the TextBox to pop a little more when an error occurs.  Looking at the original Style code, we see that we have a Trigger that changes the Style when Validation.HasError is True.  In the default example, we are providing a ToolTip.  Here I’ve added some code to make the Background color of the TextBox Red and the Foreground White whenever an error occurs:

    TargetType="{x:Type TextBox}">
                Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
                Value="Red" />
                Value="White" />

Now the user should definitely notice when an error occurs!  Again, I recommend you experiment and see what else you can do to spice up your validation errors.

And another thing…

Another thing that would be very useful is to be able to bind to the state of validation.  In other words, I have a button that I only want enabled if there are no Validation errors.

In WinForms, I used to process through all the Controls and check to see if any of them had a non-blank entry in the errorProvider.  In WPF, what I would really like is to be able to bind IsEnabled to a “HasErrors” property somewhere.  Unfortunately I couldn’t make something so simple work.  I did, however, come up with a solution using a RoutedCommand.  Commands and commanding are a topic for another time, but here is the short version of what I did. 

I created a static RoutedCommand object in my Window class:

public static RoutedCommand ValidateEntryCommand = new RoutedCommand();

I then added the supporting CommandBinding to my XAML file, including CanExecute:

        Command="{x:Static ValidationRulesPlay:Window1.ValidateEntryCommand}"
        CanExecute="CommandBinding_CanExecute" />

In the CanExecute event handler, I call Validation.HasError(DependencyObject) for each TextBox I want to validate against and set the event args CanExecute property based on the results.

private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    bool hasError = Validation.GetHasError(Int1TextBox) ||

    e.CanExecute = !hasError;

Lastly, I set the Command property of the SaveButton to my Command name.

    Command="{x:Static local:Window1.ValidateEntryCommand}"/>

Now, the button will be disabled if either of the TextBoxes have an error condition.


I hope this distills some of the basics for you and gets you on your way to writing your own custom validation rules.  As always, comments are encouraged.

You can download the full solution for this project, which includes some supporting code.

About these ads
Categories: WPF, XAML
  1. September 1, 2010 at 3:31 pm

    One problem I found with ValidationRules in place of IDataErrorInfo is that passing a particular, non-static value to a ValidationRule via Binding is a pain in the butt. I switched to using IDataErrorInfo because by the time I get into the this[string] property to assemble the error message, the rest of my IDataErrorInfo-implementing instance is filled out with the dynamic data I need, so no Binding is necessary to pass it along.

  2. Randy Maloney
    March 6, 2012 at 8:04 am

    Link to source code is dead, can you please provide?

    • February 8, 2013 at 7:39 am

      Please read the last post on this blog from Sept 2012:

  3. NightLord
    April 8, 2013 at 4:49 am

    Hi, I learn a lot from your blog, but if there is any way to get the full solution for this sample? I can’t find it in http://joelcochran.com

    • April 19, 2013 at 8:52 am

      Sorry, most of that code was lost long ago :-(

  1. October 14, 2009 at 9:21 am
  2. December 1, 2010 at 8:27 am
Comments are closed.

Get every new post delivered to your Inbox.

Join 30 other followers

%d bloggers like this: