How to: Implement Binding Validation
This example shows how to use an ErrorTemplate and a style trigger to provide visual feedback to inform the user when an invalid value is entered, based on a custom validation rule.
Example
The text content of the TextBox in the following example is bound to the Age
property (of type int) of a binding source object named ods
. The binding is set up to use a validation rule named AgeRangeRule
so that if the user enters non-numeric characters or a value that is smaller than 21 or greater than 130, a red exclamation mark appears next to the text box and a tool tip with the error message appears when the user moves the mouse over the text box.
<TextBox Name="textBox1" Width="50" FontSize="15"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
Style="{StaticResource textBoxInError}"
Grid.Row="1" Grid.Column="1" Margin="2">
<TextBox.Text>
<Binding Path="Age" Source="{StaticResource ods}"
UpdateSourceTrigger="PropertyChanged" >
<Binding.ValidationRules>
<local:AgeRangeRule Min="21" Max="130"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
The following example shows the implementation of AgeRangeRule
, which inherits from ValidationRule and overrides the Validate method. The Int32.Parse
method is called on the value to make sure that it does not contain any invalid characters. The Validate method returns a ValidationResult that indicates if the value is valid based on whether an exception is caught during the parsing and whether the age value is outside of the lower and upper bounds.
public class AgeRangeRule : ValidationRule
{
public int Min { get; set; }
public int Max { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int age = 0;
try
{
if (((string)value).Length > 0)
age = int.Parse((String)value);
}
catch (Exception e)
{
return new ValidationResult(false, $"Illegal characters or {e.Message}");
}
if ((age < Min) || (age > Max))
{
return new ValidationResult(false,
$"Please enter an age in the range: {Min}-{Max}.");
}
return ValidationResult.ValidResult;
}
}
Public Class AgeRangeRule
Inherits ValidationRule
' Properties
Public Property Max As Integer
Public Property Min As Integer
' Methods
Public Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult
Dim num1 As Integer = 0
Try
If (CStr(value).Length > 0) Then
num1 = Integer.Parse(CStr(value))
End If
Catch exception1 As Exception
Return New ValidationResult(False, $"Illegal characters or {exception1.Message}")
End Try
If ((num1 < Min) OrElse (num1 > Max)) Then
Return New ValidationResult(False, $"Please enter an age in the range: {Min}-{Max}.")
End If
Return ValidationResult.ValidResult
End Function
End Class
The following example shows the custom ControlTemplate validationTemplate
that creates a red exclamation mark to notify the user of a validation error. Control templates are used to redefine the appearance of a control.
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
As shown in the following example, the ToolTip that shows the error message is created using the style named textBoxInError
. If the value of HasError is true
, the trigger sets the tool tip of the current TextBox to its first validation error. The RelativeSource is set to Self, referring to the current element.
<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Data object
The following snippet is the data object used in the previous code examples. An instance is created in the XAML as a static resource with the key of ods
:
public class MyDataSource
{
public MyDataSource()
{
Age = 0;
Age2 = 0;
}
public int Age { get; set; }
public int Age2 { get; set; }
public int Age3 { get; set; }
}
Public Class MyDataSource
Public Sub New()
Me.Age = 0
Me.Age2 = 0
End Sub
Public Property Age As Integer
Public Property Age2 As Integer
Public Property Age3 As Integer
End Class
Complete example
For the complete example, see Bind Validation sample.
Note that if you do not provide a custom ErrorTemplate the default error template appears to provide visual feedback to the user when there is a validation error. See "Data Validation" in Data Binding Overview for more information. Also, WPF provides a built-in validation rule that catches exceptions that are thrown during the update of the binding source property. For more information, see ExceptionValidationRule.
See also
.NET Desktop feedback