首先成立一个demo用以学习和尝试WPF Data Validation机制。创建一个数据实体类:
public class Employee
{
public string Name { get; set; }
public int? Age { get; set; }
}
创建一个用户控件或者窗口,用以输入Name和Age,如下:
<Grid Width="400" Height="200">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="User Name:"VerticalAlignment="Center"/>
<TextBox Grid.Column="1" x:Name="tb" Height="30">
<TextBox.Text>
<Binding Path="Name">
<Binding.ValidationRules>
<local:NotNullValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="Age" Grid.Row="1"VerticalAlignment="Center"/>
<TextBox Grid.Row="1"Grid.Column="1" Height="30">
<TextBox.Text>
<Binding Path="Age">
<Binding.ValidationRules>
<local:NotNullValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Grid.Row="2"Grid.Column="1" Content="Save" Width="60" Height="23"/>
</Grid>
在后置代码中连接数据上下文,如下:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Employee p = new Employee();
DataContext = p;
}
要运行此demo还需要创建一NotNullValidationRule 类,数据验证的事情正是在此类中完成,此类的代码如下:
public class NotNullValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value == null || string.IsNullOrWhiteSpace(value as string))
{
return new ValidationResult(false, "value cannot benull");
}
return ValidationResult.ValidResult;
}
}
可以看到,此类必需从ValidationRule派生,然后重写Validate要领,参数value就是设置数据绑定的控件属性所暗示的值。在我们的示例中,value就是TextBox.Text的值,也就是用户输入的文本。验证逻辑非常简单,不再赘述。验证完成后需要返回一个ValidationResult 东西暗示验证功效,如果验证的数据无效,就需要为验证功效指定一个字符串作为错误信息反馈给用户。
好了,此刻demo可以运行了,在暗示Name的文本框中输入一些字符,然后删除所有适才输入的字符,最后按下tab键让焦点分开改文本框。可以看见文本框呈现了一个红色边框。显然,红色边框不是很美不雅观,而且验证错误信息也没有通过Tooltip的方法泛起出来,记得以前是可以的,此刻用的是.NetFramework 4.5,是没有Tooltip提示的。下面我们就自界说一下验证堕落时的UI显示。
验证错误的显示样式是由Validation.ErrorTemplate来控制的,这是一个关联属性,类型是ControlTemplate,下面是一个验证错误控件模板的示例:
<ControlTemplate x:Key="ErrorTempalte">
<StackPanel Orientation="Horizontal">
<StackPanel.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="bd">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="bd"Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="1" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
<AdornedElementPlaceholder/>
<Border CornerRadius="3"BorderBrush="DarkMagenta" Background="#AAFF0000"BorderThickness="1" Padding="5 2" x:Name="bd">
<Border.RenderTransform>
<ScaleTransform/>
</Border.RenderTransform>
<TextBlock Foreground="White" VerticalAlignment="Center" Text="{BindingPath=http://www.mamicode.com/ErrorContent}"/>
</Border>
</StackPanel>
</ControlTemplate>
把以上模板应用到TextBox,
<TextBox Validation.ErrorTemplate="{StaticResource ErrorTempalte}">…
再次运行demo,当焦点分开文本框后,会有一个红色的错误提示显示在文本框的右边,而且还有一个X安心的放大动画,使界面变得有一些动感了。对付这个ControlTemplate,需要记住的是,模板根元素的DataContext是一个ValidationError东西的列表,而在上面的模板中,我们将列表中第一个东西的ErrorContent显示了出来(实际上,当一个绑定有多个ValidationRule的时候,WPF绑定引擎一旦发明有一个ValidationRule验证掉败,那么后续的ValidationRule将不会被执行),ErrorContent属性就是我们在结构函数中指定的错误信息。此外一个需要注意的是,这个模板中的界面元素是显示在AdornerLayer中的;要将显示错误的界面元素显示在被验证控件的周围,需要AdornedElementPlaceholder元素的撑持,该元素是一个占位符,跟被验证控件有着同样的位置和尺寸;而且还可以通过此类的AdornedElement属性来访谒被验证控件。