具有依赖属性的 WPF ValidationRule
假设您有一个继承自 ValidationRule 的类:
public class MyValidationRule : ValidationRule
{
public string ValidationType { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {}
}
在 XAML 中,您像这样进行验证:
<ComboBox.SelectedItem>
<Binding Path="MyPath" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
<Binding.ValidationRules>
<qmvalidation:MyValidationRule ValidationType="notnull"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
哪个有效且一切正常。
但现在假设您希望拥有 ValidationType="{Binding MyBinding}"
,其中 MyBinding
来自 DataContext
。
为此,我需要将 MyValidationRule
创建为 DependencyObject
并添加 Dependency Property。
我尝试编写一个 DependencyObject
类,并绑定它。但有两个问题...... ValidationRule
没有来自组合框/项目的 DataContext
。
您对如何解决这个问题有什么想法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于
ValidationRule
不是从DependencyObject
继承的,因此您无法在自定义验证类中创建DependecyProperty
。但是,正如 此链接中所述 您可以在验证类中拥有一个继承自
DependecyObject
类型的普通属性,并在该类中创建一个DependencyProperty
。例如,这里是一个支持可绑定属性的自定义
ValidationRule
类:ComparisonValue
是一个继承自DependencyObject
的简单类,并具有DependencyProperty
:这解决了原来的问题,但不幸的是又带来了两个问题:
绑定无法正常工作,因为
ValidationRules
不是可视化树的一部分,因此无法正确获取绑定属性。例如,这种幼稚的方法是行不通的:相反,应该按照这个答案中的说明使用代理对象:
BindingProxy
是一个简单的类:如果自定义
ValidationRule
中的属性绑定到另一个对象的属性,则当其他对象的属性更改时,将不会触发原始属性的验证逻辑。< /p>为了解决这个问题,我们应该在
ValidationRule
的绑定属性更新时更新绑定。首先,我们应该将该属性绑定到我们的 ComparisonValue 类。然后,我们可以在Value
属性更改时更新绑定的源:这里也存在与第一种情况相同的代理问题。因此我们应该创建另一个代理对象:
在本例中,
TextBoxToValidate
的Text
属性根据SomeCollection
的Items.Count
属性进行验证。当列表中的项目数发生变化时,将触发Text
属性的验证。Since
ValidationRule
does not inherit fromDependencyObject
you cannot create aDependecyProperty
in your custom validation class.However as explained in this link you can have a normal property in your validation class which is of a type that inherits from
DependecyObject
and create aDependencyProperty
in that class.For example here is a custom
ValidationRule
class that support bindable property:ComparisonValue
is a simple class that inherits fromDependencyObject
and has aDependencyProperty
:This solves the original problem but unfortunately brings two more problems:
The binding does not work correctly since the
ValidationRules
is not part of visual tree and therefore cannot get the bound property correctly. For example this naive approach will not work:Instead a proxy object should be used as explained in this answer:
BindingProxy
is a simple class:If the property in custom
ValidationRule
is bound to another object's property, the validation logic for the original property will not fire when that other object's property changes.To solve this problem we should update the binding when the
ValidationRule
's bound property is updated. First we should bind that property to ourComparisonValue
class. Then, we can update the source of the binding when theValue
property changes:The same proxy problem in the first case also exists here. Therefore we should create another proxy object:
In this case the
Text
property ofTextBoxToValidate
is validated against theItems.Count
property ofSomeCollection
. When the number of items in the list changes, the validation for theText
property will be triggered.