一个比较Hack的方法是

时间:2022-01-12 08:54:22

首先成立一个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属性来访谒被验证控件。