假设您有一个从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,并添加一个依赖项属性。
我试图编写一个类,即DependencyObject,并绑定它。但是有两个问题..。ValidationRule没有来自Combobox / Item的DataContext。
你对如何解决这个问题有什么想法吗?
发布于 2016-07-13 13:31:31
由于ValidationRule不是从DependencyObject继承的,所以不能在自定义验证类中创建DependecyProperty。
但是,正如在此链接中解释的那样,验证类中可以有一个正常的属性,它的类型是从DependecyObject继承并在该类中创建DependencyProperty的类型。
例如,这里有一个支持可绑定属性的自定义ValidationRule类:
[ContentProperty("ComparisonValue")]
public class GreaterThanValidationRule : ValidationRule
{
public ComparisonValue ComparisonValue { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string s = value?.ToString();
int number;
if (!Int32.TryParse(s, out number))
{
return new ValidationResult(false, "Not a valid entry");
}
if (number <= ComparisonValue.Value)
{
return new ValidationResult(false, $"Number should be greater than {ComparisonValue}");
}
return ValidationResult.ValidResult;
}
}ComparisonValue是一个简单的类,它继承自DependencyObject,并具有一个DependencyProperty
public class ComparisonValue : DependencyObject
{
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
nameof(Value),
typeof(int),
typeof(ComparisonValue),
new PropertyMetadata(default(int));这解决了原来的问题,但不幸的是,它带来了另外两个问题:
ValidationRules不是可视树的一部分,因此无法正确地获得绑定属性。例如,这种天真的方法不起作用:
<:比较值Value="{Binding Text,ElementName=TextBoxToValidate}"/> :GreaterThanValidationRule>
相反,应该使用代理对象,如这答案中所解释的那样:
BindingProxy是一个简单的类:
公共类BindingProxy :可冻结的{受保护的覆盖可冻结的CreateInstanceCore() {返回新的BindingProxy();}公共对象数据{ get {返回GetValue( DataProperty );} set { SetValue(DataProperty,值);}公共静态只读DependencyProperty DataProperty=DependencyProperty.Register(名称(数据)、类型(对象)、类型(BindingProxy)、新的UIPropertyMetadata(null));}ValidationRule中的属性绑定到另一个对象的属性,则当其他对象的属性更改时,原始属性的验证逻辑将不会触发。
为了解决这个问题,我们应该在更新ValidationRule的绑定属性时更新绑定。首先,我们应该将该属性绑定到我们的ComparisonValue类。然后,当Value属性发生变化时,我们可以更新绑定的源:
公共类ComparisonValue : DependencyObject { public int值{ get { class (int)GetValue( ValueProperty );} set { SetValue(ValueProperty,value);}公共静态只读DependencyProperty ValueProperty= DependencyProperty.Register(名称(值)、类型(Int)、类型(ComparisonValue)、新PropertyMetadata(默认值(Int)、OnValueChanged));私有静态空OnValueChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { ComparisonValue comparisonValue = (ComparisonValue) d;BindingExpressionBase bindingExpressionBase =ComparisonValue BindingToTriggerProperty;bindingExpressionBase?.UpdateSource();}公共对象BindingToTrigger { get {value( BindingToTriggerProperty);} set { SetValue(BindingToTriggerProperty,value);}公共静态只读FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));BindingToTriggerProperty = DependencyProperty.Register(名称(BindingToTrigger)、类型(对象)、类型(ComparisonValue)、新FrameworkPropertyMetadata(默认(对象))、BindingToTriggerProperty}
在第一种情况下,同样的代理问题也存在于这里。因此,我们应该创建另一个代理对象:
{en19#}}“”{Binding,Source={StaticResource SourceProxy}}"/>
在这种情况下,Text属性TextBoxToValidate将根据SomeCollection的Items.Count属性进行验证。当列表中的项数发生变化时,将触发Text属性的验证。https://stackoverflow.com/questions/3862385
复制相似问题