如何为 class 的 属性 生成错误

How to generate an error for a property of a class

我有一个具有 属性 的 ViewModel。 这个属性是一个"PhysicalValue"。这个 PhysicalValue 是由一个 Value 和一个 Unit 组成的 class。

public Class MyViewModel:INotifyPropertyChanged:IDataErrorInfo {
    public PhysicalValue Target {get => _target; set => {_target = value; NotifyPropertyChanged("Target");}}

    public string this[string columnName]
    {
        get
        {
            if (columnName == "Target")
            {
                if(_target.Value>5000){
                    return "out of spec value";
                }
            }
            return String.Empty;
        }
    }   
}

我有一个控件应该编辑此 PhysicalValue 的值:

[...]
<dxe:TextEdit EditValue="{Binding Target.Value, ValidatesOnDataErrors =true}"></dxe:TextEdit>
[...]

但我没有错误(可能是因为它搜索 Target.Value 有错误。我尝试了另一种方法,直接绑定到 Target,但这不起作用,因为我需要 convertBack 来知道最初使用哪个 Unit 来重建 PhysicalValue。

你会如何解决这个问题?

您的 TextEdit 控件的 EditValue 属性 绑定到 PhysicalValue.Value。当您将 Binding.ValidatesOnDataErrors 设置为 true 时,绑定引擎会检查具有目标 属性 的 class 是否实现了 IDataErrorInfo。 所以为了这个工作 PhysicalValue class 需要实施 IDataErrorInfo:

class PhysicalValue : IDataErrorInfo
{
    public double Value { get; set; }

    public object Unit { get; set; }

    public string Error => this["Value"] + this["Unit"];

    public PhysicalValue(int v, object u)
    {
        Value = v;
        Unit = u;
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "Value")
            {
                if (Value > 5000)
                {
                    return "out of spec value";
                }
            }
            return String.Empty;
        }
    }
}

如果 PhysicalValue class 无法保存验证逻辑或无法实现 IDataErrorInfo 接口,您可以创建一个代理 class 来处理验证并绑定到该代理。这是一个小例子:

class PhysicalValueValidator : IDataErrorInfo
{
    private readonly PhysicalValue _physicalValue;
    private double _maxValue;

    public double Value
    {
        get { return _physicalValue.Value; }
        set { _physicalValue.Value = value; }
    }

    public PhysicalValueValidator(PhysicalValue pv)
    {
        _physicalValue = pv;
        _maxValue = 5000;
    }

    public void SetMaxValue(double maxValue)
    {
        _maxValue = maxValue;
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "Value")
            {
                if (Value > _maxValue)
                {
                    return "out of spec value";
                }
            }
            return String.Empty;
        }
    }

    public string Error => this["Value"];
}

PhysicalValueValidator class 公开了 SetMaxValue(..) 方法来更新窗格视图模型的验证逻辑。视图模型可能如下所示:

class MyViewModel 
{
    private PhysicalValue _target;

    public PhysicalValueValidator TargetValidator { get; }

    public MyViewModel()
    { 
        _target = new PhysicalValue(5, 10);
        TargetValidator = new PhysicalValueValidator(_target);

        // update validation Logic...
        TargetValidator.SetMaxValue(6000);
    }
}

在您的 xaml 代码中,绑定到 TargetValidator.Value 而不是 Target.Value。

有关 IDataErrorInfo 的更多信息,请查看此 link:IDataErrorInfo