Introduction
There are plenty of articles about WPF and validation rules, but this article will show you a basic implementation of validation rules you can attach to textboxes to provide quick and simple validation based on specified types.
Background
This article will not go into detail of the WPF validation rule feature but will try to explain the general workings. The SimpleValidator
is an attached behaviour that can be attached to a TextBox
control (possibly other controls later) with a specific type you wish to validate. There are three (3) other optional properties you can use to set the upper bound and lower bound of number types or to specify that the value cannot be empty. Let's see some usages.
Using the Code
There is very little to explain about using the code for it is relatively simple and straight forward. Say we have a TextBox
and wish that only numbers (Double
) values will be valid. We need to proceed to bind (validation only works on data-bound controls) the Text
property to our code-behind (or ViewModel
) text. Setting the UpdateSourceTrigger
to PropertyChanged
ensures that validation happens on every keystroke.
Now we use the attached property to set the type we wish to use (i.e. Double
):
<TextBox Text="{Binding BackingText, UpdateSourceTrigger=PropertyChanged}"
validator:SimpleValidator.ValidationType="{x:Type system:Double}" />
Remembering that system namespace can be declared as follows:
xmlns:system="clr-namespace:System;assembly=mscorlib"
To set an upper bound and lower bound to the validation, we simply use as follows:
<TextBox Text="{Binding BackingText, UpdateSourceTrigger=PropertyChanged}"
validator:SimpleValidator.UpperRange="20"
validator:SimpleValidator.LowerRange="5"
validator:SimpleValidator.ValidationType="{x:Type system:Double}" />
This will cause our TextBox
to only accept numbers (Double
) between the range of five (5) and twenty (20) inclusive. All other values and characters will be rejected. Finally, using the NoEmptyValue
property will reject any string
value that is empty (after stripping away leading and trailing empty spaces).
<TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
validator:SimpleValidator.NoEmptyValue="True" />
How It Works
I will try to briefly describe the workings for those that are curious, but from examining the source code, it's pretty straight forward. The key point of the features is here:
element.Loaded += (s, e) =>
{
var validation = new SimpleValidator(GetValidationType(obj),
GetUpperRange(obj), GetLowerRange(obj), GetNoEmptyValue(obj));
Binding binding = BindingOperations.GetBinding(obj, TextBox.TextProperty);
if (binding != null)
if (!binding.ValidationRules.Contains(validation))
binding.ValidationRules.Add(validation);
};
Basically what happens is when the element is loaded (so that all the bindings are in place), we will create a new instance of our validation rule class and send in the rules we need to validate. We then get the binding from the element's Text
dependency property (could be others later on) and add the new validation rule class to it if it doesn't already exist (to avoid multiplicity).
Feedback
This is my first article and any feedback would be greatly welcomed. Please send me any improvement suggestions on how to get this to work for controls other than TextBox
.
History
- 23rd October, 2009: Initial post