gpt4 book ai didi

具有依赖属性的 WPF ValidationRule

转载 作者:行者123 更新时间:2023-12-03 14:05:20 30 4
gpt4 key购买 nike

假设你有一个继承自 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 , 并绑定(bind)它。不过有两个问题.. ValidationRule没有 DataContext从组合框/项目。
你有什么想法,如何解决这个问题?

最佳答案

由于ValidationRule不继承自 DependencyObject您不能创建 DependecyProperty在您的自定义验证类中。

然而正如 this link 中所解释的那样你可以在你的验证类中拥有一个继承自 DependecyObject 的类型的普通属性。并创建一个 DependencyProperty在那个类(class)。

例如这里是一个自定义 ValidationRule支持可绑定(bind)属性的类:

[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 以来,绑定(bind)无法正常工作不是可视树的一部分,因此无法正确获取绑定(bind)属性。例如,这种天真的方法行不通:
    <TextBox Name="TextBoxToValidate">
    <TextBox.Text>
    <Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
    <Binding.ValidationRules>
    <numbers:GreaterThanValidationRule>
    <numbers:ComparisonValue Value="{Binding Text, ElementName=TextBoxToValidate}"/>
    </numbers:GreaterThanValidationRule>
    </Binding.ValidationRules>
    </Binding>
    </TextBox.Text>
    </TextBox>

    相反,应该使用代理对象,如 this 中所述。回答:
    <TextBox Name="TextBoxToValidate">
    <TextBox.Resources>
    <bindingExtensions:BindingProxy x:Key="TargetProxy" Data="{Binding Path=Text, ElementName=TextBoxToValidate}"/>
    </TextBox.Resources>
    <TextBox.Text>
    <Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
    <Binding.ValidationRules>
    <numbers:GreaterThanValidationRule>
    <numbers:ComparisonValue Value="{Binding Data, Source={StaticResource TargetProxy}}"/>
    </numbers:GreaterThanValidationRule>
    </Binding.ValidationRules>
    </Binding>
    </TextBox.Text>
    </TextBox>
    BindingProxy是一个简单的类:
    public class BindingProxy : Freezable
    {
    protected override Freezable CreateInstanceCore()
    {
    return new BindingProxy();
    }

    public object Data
    {
    get { return GetValue(DataProperty); }
    set { SetValue(DataProperty, value); }
    }
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }


  • 如果自定义属性ValidationRule绑定(bind)到另一个对象的属性,当另一个对象的属性更改时,原始属性的验证逻辑将不会触发。

    为了解决这个问题,我们应该在 ValidationRule 时更新绑定(bind)。的绑定(bind)属性已更新。首先我们应该将该属性绑定(bind)到我们的ComparisonValue。类(class)。然后,我们可以在 Value 时更新绑定(bind)源。属性变化:
    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), OnValueChanged));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    ComparisonValue comparisonValue = (ComparisonValue) d;
    BindingExpressionBase bindingExpressionBase = BindingOperations.GetBindingExpressionBase(comparisonValue, BindingToTriggerProperty);
    bindingExpressionBase?.UpdateSource();
    }

    public object BindingToTrigger
    {
    get { return GetValue(BindingToTriggerProperty); }
    set { SetValue(BindingToTriggerProperty, value); }
    }
    public static readonly DependencyProperty BindingToTriggerProperty = DependencyProperty.Register(
    nameof(BindingToTrigger),
    typeof(object),
    typeof(ComparisonValue),
    new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    }

    第一种情况下同样的代理问题也存在这里。因此我们应该创建另一个代理对象:
    <ItemsControl Name="SomeCollection" ItemsSource="{Binding ViewModelCollectionSource}"/>

    <TextBox Name="TextBoxToValidate">
    <TextBox.Resources>
    <bindingExtensions:BindingProxy x:Key="TargetProxy" Data="{Binding Path=Items.Count, ElementName=SomeCollection}"/>
    <bindingExtensions:BindingProxy x:Key="SourceProxy" Data="{Binding Path=Text, ElementName=TextBoxToValidate, Mode=TwoWay}"/>
    </TextBox.Resources>
    <TextBox.Text>
    <Binding Path="ViewModelProperty" UpdateSourceTrigger="PropertyChanged">
    <Binding.ValidationRules>
    <numbers:GreaterThanValidationRule>
    <numbers:ComparisonValue Value="{Binding Data, Source={StaticResource TargetProxy}}" BindingToTrigger="{Binding Data, Source={StaticResource SourceProxy}}"/>
    </numbers:GreaterThanValidationRule>
    </Binding.ValidationRules>
    </Binding>
    </TextBox.Text>
    </TextBox>

    在这种情况下,Text TextBoxToValidate 的属性(property)根据 Items.Count 进行验证SomeCollection 的属性(property).当列表中的项目数发生变化时,Text 的验证属性将被触发。
  • 关于具有依赖属性的 WPF ValidationRule,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3862385/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com