如何验证彼此依赖的两个属性?

问题描述 投票:6回答:1

我具有具有2个属性的视图模型:AB,并且我想验证该A < B

下面是我使用自定义验证规则的简化实现。由于每个属性都是独立验证的,因此会产生麻烦的问题:如果输入的A值无效,则即使更改B后它仍然保持无效,因为B的验证对A一无所知。

可以在此演示中看到:

A在输入11后无效,这是正确的,因为11 > 2。将B更改为22不会重新评估A,我必须编辑A才能通过验证。

我想要什么?我希望在将22注入B后,红色边框(验证错误)消失并且A = 11, B = 22将成为视图模型中的源值。

在新的B值与源同步之后,如何在A验证中以某种方式强制B验证?


查看模型:

public class ViewModel : INotifyPropertyChanged
{
    int _a;
    public int A
    {
        get => _a;
        set
        {
            _a = value;
            OnPropertyChanged();
        }
    }

    int _b;
    public int B
    {
        get => _b;
        set
        {
            _b = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public virtual void OnPropertyChanged([CallerMemberName] string property = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}

查看:

<StackPanel>
    <TextBox Margin="10" Text="{local:MyBinding A}" />
    <TextBox Margin="10" Text="{local:MyBinding B}" />
</StackPanel>

查看代码:

public MainWindow()
{
    InitializeComponent();
    DataContext = new ViewModel { A = 1, B = 2 };
}

绑定:

public class MyBinding : Binding
{
    public MyBinding(string path) : base(path)
    {
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        ValidationRules.Add(new MyValidationRule());
    }
}

验证规则:

public class MyValidationRule : ValidationRule
{
    public MyValidationRule() : base(ValidationStep.ConvertedProposedValue, false) { }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo) => ValidationResult.ValidResult; // not used

    public override ValidationResult Validate(object value, CultureInfo cultureInfo, BindingExpressionBase owner)
    {
        var binding = owner as BindingExpression;
        var vm = binding?.DataItem as ViewModel;
        switch (binding.ResolvedSourcePropertyName)
        {
            case nameof(vm.A):
                if ((int)value >= vm.B)
                    return new ValidationResult(false, "A should be smaller than B");
                break;
            case nameof(vm.B):
                if ((int)value <= vm.A)
                    return new ValidationResult(false, "B should be bigger than A");
                break;
        }
        return base.Validate(value, cultureInfo, owner);
    }
}
c# wpf validation dependencies
1个回答
4
投票

[ValidationRules不支持在设置另一个属性时使一个属性无效。

您应该执行的是在视图模型中实现INotifyDataErrorInfo并在每次刷新属性的验证状态时引发INotifyDataErrorInfo事件。

ErrorsChanged中有一个可用的示例。

© www.soinside.com 2019 - 2024. All rights reserved.