WPF绑定只读附加属性Validation.HasErrors的方案原理澄清
该WPF绑定方案实现原理讲解
核心解决的问题
WPF 中 Validation.HasError 是系统定义的只读附加依赖属性,默认不支持直接使用 OneWayToSource 绑定模式把校验状态同步到 ViewModel,本方案通过「附加属性挂载+中间代理层」的方式绕过了这个限制。
代码逻辑分层拆解
1. OneWayToSource 静态类(附加属性挂载层)
这个类的作用是把自定义的代理对象挂到目标控件(比如示例中的TextBox)上:
- 注册了名为
Bindings的附加依赖属性,支持挂载到所有FrameworkElement类型的控件上 - 当附加属性被赋值/修改时,会触发
OnBindingsChanged回调,自动把当前的目标控件赋值给代理对象的内部Element属性,建立代理和目标控件的关联
2. OneWayToSourceBindings 类(值同步代理层)
这是实现值搬运的核心类,继承 FrameworkElement 是为了获得绑定能力和 DataContext 属性:
关联目标控件后的动作
当代理对象的 Element 属性被赋值为目标控件后,会触发 OnElementChanged 回调,完成两个绑定初始化:
- 给代理对象自身的
DataContext做绑定,源为目标控件的DataContext,这样代理就和目标控件共享同一个 ViewModel 上下文,保证 XAML 中写的绑定能正常找到源 - 给代理对象的内部附加属性
HasErrorProxy做绑定,源为目标控件的Validation.HasError只读属性,只要目标控件的校验状态变化,HasErrorProxy的值会同步更新
值传递链路
HasErrorProxy值变化时触发OnHasErrorProxyChanged回调,通过SetCurrentValue方法给代理类的HasError属性赋值:这个方法不会破坏 XAML 中给HasError写的绑定,只会更新属性的当前值HasError是自定义的可写依赖属性,默认开启了双向绑定配置,它的值变化后会自动同步到绑定的 ViewModel 属性上,完成只读属性值到 ViewModel 的传递
3. XAML 部分使用逻辑
示例中的XAML做了两件事:
- 给 TextBox 挂载
OneWayToSource.Bindings附加属性,值为OneWayToSourceBindings代理实例 - 把代理实例的
HasError属性绑定到 ViewModel 的ValueInVM属性,打通整个值同步链路:TextBox.Validation.HasError→OneWayToSourceBindings.HasErrorProxy→OneWayToSourceBindings.HasError→ViewModel.ValueInVM
内容的提问来源于stack exchange,提问作者Semyon Mart
相关产品推荐
相关产品推荐

