文章目录
## 实体类定义
WPF要实现表单数据输入验证,必须实现接口IDataErrorInfo,或者INotifyDataErrorInfo。IDataErrorInfo是验证单个字段,INotifyDataErrorInfo是用于验证所有字段,本文采用IDataErrorInfo来实现。
实体类基类

实体类
字段中注解RequiredEx、StringLengthEx为自定义的特性用于获取多语言资源显示国际化的提示
Validation.ErrorTemplate模板定义与应用
最后几句TextBox的样式把模板应用到了TextBox
<ControlTemplate x:Key="validationTemplate">
<StackPanel>
<Border BorderThickness="1"
BorderBrush="Red"
Opacity="0">
<Border.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard BeginTime="0:0:0.000">
<DoubleAnimation BeginTime="0:0:0.000"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
<DoubleAnimation BeginTime="0:0:0.300"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="0" />
<DoubleAnimation BeginTime="0:0:0.600"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
<DoubleAnimation BeginTime="0:0:0.900"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="0" />
<DoubleAnimation BeginTime="0:0:1.200"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
<DoubleAnimation BeginTime="0:0:1.500"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="0" />
<DoubleAnimation BeginTime="0:0:1.800"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
<DoubleAnimation BeginTime="0:0:2.100"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="0" />
<DoubleAnimation BeginTime="0:0:2.400"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
<DoubleAnimation BeginTime="0:0:2.700"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="0" />
<DoubleAnimation BeginTime="0:0:3.000"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.300"
To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<AdornedElementPlaceholder Name="placeholder">
<Popup Name="ValidationPopup"
AllowsTransparency="true"
IsOpen="false"
PlacementTarget="{Binding ElementName=placeholder, Mode=OneWay}">
<Grid Name="Root"
Margin="4">
<Border Background="LightGray"
CornerRadius="2">
<Border.Resources>
<DataTemplate DataType="{x:Type ValidationError}">
<TextBlock MaxWidth="250"
Margin="8,4"
Foreground="Red"
TextWrapping="Wrap"
UseLayoutRounding="false"
Text="{Binding ErrorContent}" />
</DataTemplate>
</Border.Resources>
<ItemsControl ItemsSource="{Binding}" />
</Border>
</Grid>
</Popup>
</AdornedElementPlaceholder>
</Border>
</StackPanel>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=placeholder, Path=AdornedElement.IsKeyboardFocusWithin, Mode=OneWay}"
Value="True" />
<Condition Binding="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.HasError), Mode=OneWay}"
Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="ValidationPopup"
Property="IsOpen"
Value="true" />
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate"
Value="{StaticResource validationTemplate}" />
</Style>
Xaml中应用验证模板
注意:绑定实体属性时,要设置ValidatesOnDataErrors=True,才会触发数据验证
<Grid Margin="5"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="label" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{StaticResource UserName}"
VerticalAlignment="Center"
Margin="0,0,10,0"></TextBlock>
<TextBlock Text="*"
VerticalAlignment="Center"
Foreground="Red"
HorizontalAlignment="Right"
FontWeight="Bold"
FontSize="16"
ToolTip="必选项"></TextBlock>
<TextBox Grid.Column="1"
Text="{Binding User.UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Validation.ErrorTemplate="{StaticResource validationTemplate}"></TextBox>
</Grid>