<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:WpfApplication1" x:Class="WpfApplication1.Window1"> <Window.Resources> <c:MyDataSource x:Key="ods"/> <ControlTemplate x:Key="validationTemplate"> <DockPanel> <TextBlock Foreground="Red" FontSize="20">!</TextBlock> <AdornedElementPlaceholder/> </DockPanel> </ControlTemplate> <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> </Window.Resources> <StackPanel> <TextBox Name="textBox3" Width="50" FontSize="15" Validation.ErrorTemplate="{StaticResource validationTemplate}" Style="{StaticResource textBoxInError}"> <TextBox.Text> <Binding Path="Age3" Source="{StaticResource ods}" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <ExceptionValidationRule/> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> <CheckBox Name="cb" Checked="UseCustomHandler" Unchecked="DisableCustomHandler">Enable Custom Handler (see ToolTip)</CheckBox> </StackPanel> </Window> //File:Window.xaml.cs using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Data; using System.Globalization; using System.Collections.ObjectModel; namespace WpfApplication1 { public partial class Window1 : Window { public Window1() { InitializeComponent(); } void UseCustomHandler(object sender, RoutedEventArgs e) { BindingExpression myBindingExpression = textBox3.GetBindingExpression(TextBox.TextProperty); Binding myBinding = myBindingExpression.ParentBinding; myBinding.UpdateSourceExceptionFilter = new UpdateSourceExceptionFilterCallback(ReturnExceptionHandler); myBindingExpression.UpdateSource(); } void DisableCustomHandler(object sender, RoutedEventArgs e) { Binding myBinding = BindingOperations.GetBinding(textBox3, TextBox.TextProperty); myBinding.UpdateSourceExceptionFilter -= new UpdateSourceExceptionFilterCallback(ReturnExceptionHandler); BindingOperations.GetBindingExpression(textBox3, TextBox.TextProperty).UpdateSource(); } object ReturnExceptionHandler(object bindingExpression, Exception exception) { return "This is from the UpdateSourceExceptionFilterCallBack."; } } public class AgeRangeRule : ValidationRule { private int _min; private int _max; public AgeRangeRule() { } public int Min { get { return _min; } set { _min = value; } } public int Max { get { return _max; } set { _max = value; } } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { int age = 0; try { if (((string)value).Length > 0) age = Int32.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 + "."); } else { return new ValidationResult(true, null); } } } public class MyDataSource { private int _age; private int _age2; private int _age3; public MyDataSource() { Age = 0; Age2 = 0; } public int Age { get { return _age; } set { _age = value; } } public int Age2 { get { return _age2; } set { _age2 = value; } } public int Age3 { get { return _age3; } set { _age3 = value; } } } }