WPF TextBox Validation
Sample problem: set parameter by entering value into a TextBox, check if value is a number in given range, allow clicking a Button if validation was successful.
ValidationRule
ValidationRule is an abstract class from System.Windows.Controls that helps creating custom validation rules for user input. In this example a derived class DoubleRangeRule will check if user entered a number (double) within a given range (between Max and Min value).
public class DoubleRangeRule : ValidationRule
{
public double Min { get; set; }
public double Max { get; set; }
public override ValidationResult Validate( object value,
CultureInfo cultureInfo )
{
double parameter = 0;
try
{
if( ((string) value).Length > 0 )
{
parameter = Double.Parse( (String) value );
}
}
catch( Exception e )
{
return new ValidationResult( false, "Illegal characters or "
+ e.Message );
}
if( (parameter < this.Min) || (parameter > this.Max) )
{
return new ValidationResult( false,
"Please enter value in the range: "
+ this.Min + " - " + this.Max + "." );
}
return new ValidationResult( true, null );
}
}
Validation.ErrorTemplate
Having defined ValidationRule as above if user input is invalid, TextBox will have a red border. Like everything in WPF it is possible to customize it by setting a custom ControlTemplate. My template shows a warning sign and a label explaining error made by user (why input is invalid):
<ControlTemplate x:Key="TextBoxErrorTemplate">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Image Height="16" Margin="0,0,5,0"
Source="Assets/warning_48.png"/>
<AdornedElementPlaceholder x:Name="Holder"/>
</StackPanel>
<Label Foreground="Red" Content="{Binding ElementName=Holder,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
</StackPanel>
</ControlTemplate>
Read more about AdornedElement here.
Binding to validation result
On the result of validation can depend many things. For example I would like to bind button IsEnabled property to that deciding to enable button only in user input is valid. Simplest way, in my opinion is to check if TextBox has any validation errors and if no – make button enabled, disabled otherwise. With TextBox called Box (x:Name) binding of Button's IsEnabled property looks like that:
IsEnabled="{Binding ElementName=Box, Path=(Validation.Errors)[0],
Converter={StaticResource buttonEnabled}}"
Final app
Finally we get a TexBbox with validation rules, tips on incorrect input and a Button bound to correctness of input.
<TextBox x:Name="Box"
Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}">
<TextBox.Text>
<Binding Path="ValueInBox" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ValidationExpamples:DoubleRangeRule Min="0.5" Max="10"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="SaveChanges"
IsEnabled="{Binding ElementName=Box, Path=(Validation.Errors)[0],
Converter={StaticResource buttonEnabled}}"/>
If anyone had an idea how to do things like that a better way comments would be much appreciated. VS2008 project here.
Monika