ObservableValidator自定义错误样式
1. wpf sample部分代码如下
只修改MainWindow.xaml,其他代码在上一篇
<Window x:Class="ObservableValidatorSample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:ObservableValidatorSample"mc:Ignorable="d"Title="ObservableValidator 示例" Height="450" Width="800"><Window.Resources><!-- 自定义错误显示样式 --><Style TargetType="TextBox"><Style.Triggers><Trigger Property="Validation.HasError" Value="True"><Setter Property="ToolTip"Value="{Binding (Validation.Errors)[0].ErrorContent,RelativeSource={RelativeSource Self}}" /></Trigger></Style.Triggers></Style><ControlTemplate x:Key="ValidationErrorTemplate"><DockPanel LastChildFill="True"><TextBlock Foreground="Red" FontSize="12" Margin="5,0,0,0"DockPanel.Dock="Bottom"Text="{Binding [0].ErrorContent}" /><AdornedElementPlaceholder/></DockPanel></ControlTemplate></Window.Resources><Window.DataContext><local:PersonViewModel/></Window.DataContext><StackPanel Margin="20" VerticalAlignment="Center"><TextBlock Text="姓名:"/><TextBoxMargin="0,5,0,10"Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" /><TextBlock Text="年龄:"/><TextBoxMargin="0,5,0,10"Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"Text="{Binding Age, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" /><Button Content="触发全部验证"HorizontalAlignment="Left"Width="150"Click="OnValidateClick" /></StackPanel>
</Window>
运行效果如下
2. 解释核心知识点
1. INotifyDataErrorInfo 机制
作用
INotifyDataErrorInfo
是 WPF 和其他 XAML 框架支持的数据验证接口,主要用于通知绑定系统某个属性的验证错误,从而让 UI 能够动态响应并显示错误。
关键成员
事件:
ErrorsChanged
发生在某个属性的验证错误状态发生变化时触发。UI 监听这个事件,更新显示。方法:
IEnumerable GetErrors(string propertyName)
返回指定属性当前的错误信息列表。属性:
bool HasErrors
表示是否存在任何验证错误。
工作流程
ViewModel 实现了
INotifyDataErrorInfo
后,绑定系统会自动调用GetErrors
查询错误信息,决定控件是否有错误。ViewModel 在属性值变化时执行验证逻辑,更新内部错误状态。
如果错误状态变化,ViewModel 触发
ErrorsChanged
事件,通知 UI 重新请求错误数据。UI 根据错误存在与否,应用不同的视觉样式(例如红框)和显示错误消息。
CommunityToolkit.Mvvm 的 ObservableValidator
ObservableValidator
是对INotifyDataErrorInfo
的封装,实现了错误管理和触发ErrorsChanged
。你只需要在属性上添加数据注解(如
[Required]
、[Range]
),调用ValidateProperty
/ValidateAllProperties
,它会自动完成验证并触发事件。NotifyDataErrorInfo
属性可以让属性变化时自动触发验证。
2. WPF 自定义验证错误样式原理
默认行为
绑定启用验证(例如设置了
ValidatesOnDataErrors=True
)时,WPF 会根据绑定的验证状态自动设置控件的Validation.HasError
属性。Validation.HasError
是一个附加属性,表示当前控件是否有错误。
ErrorTemplate
WPF 中控件有一个
Validation.ErrorTemplate
属性,可以自定义控件出错时的视觉表现。默认
ErrorTemplate
会显示一个红色感叹号图标在控件右侧。你可以自定义
ErrorTemplate
,实现例如:红色边框高亮控件
在控件下方显示错误文本
自定义图标或动画
ErrorTemplate 的工作原理
ErrorTemplate
是一个ControlTemplate
,通常包含一个AdornedElementPlaceholder
,它占位显示被装饰的控件本体。当控件
Validation.HasError == true
时,WPF 自动在控件外层添加一个装饰层(Adorner),显示ErrorTemplate
。这个装饰层不影响控件布局,只覆盖显示层。
绑定错误内容到 UI
绑定错误信息时,通常用表达式绑定:
Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Self}}"
这里用的是
Validation.Errors
附加属性,它存储了控件所有的错误信息集合。通过这种绑定,错误提示文本可以动态显示当前的第一个错误内容。