【问题标题】:How to generate an error for a property of a class如何为类的属性生成错误
【发布时间】:2019-02-21 14:47:24
【问题描述】:

我有一个具有属性的 ViewModel。 此属性是“PhysicalValue”。这个 PhysicalValue 是一个由 Value 和 Unit 组成的类。

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。

你会怎么解决这个问题?

【问题讨论】:

  • 这里有一个例子,如果是网站,我会使用一些客户端或html5进行输入验证,以免过度设计..stackoverflow.com/a/14023682/10634638
  • @Bestinamir 不确定是否理解您的答案。这不是布局问题。
  • 你想生成什么样的错误?您可以设置 Value 属性吗?

标签: c# wpf binding idataerrorinfo


【解决方案1】:

TextEdit 控件的EditValue 属性绑定到PhysicalValue.Value。当您将Binding.ValidatesOnDataErrors 设置为true 时,绑定引擎会检查具有目标属性的类是否实现IDataErrorInfo。 因此,要使其正常工作,PhysicalValue 类需要实现 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 类不能保存验证逻辑或不能实现IDataErrorInfo 接口,您可以创建一个代理类来处理验证并绑定到它。这是一个小例子:

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 类公开了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 的更多信息,请查看此链接:IDataErrorInfo

【讨论】:

  • 是的,问题是这个 5000 的限制确实特定于我在此窗格中的使用。我们在很多地方都用到了这个 PhysicalValue,而这个物理值目前还不能知道它是否有效。它需要调用一些方法来计算一些硬件功率限制,并使用不仅仅取决于这个值的大方程:(
  • 好的,如果验证逻辑不是特定于 PhysicalValue 而是特定于您的窗格,您可以创建一个代理类来处理验证。我会用一个简短的例子来更新我的答案
  • 这是一个非常好的主意,非常聪明和干净,我喜欢它!非常感谢!
猜你喜欢
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2014-11-27
  • 1970-01-01
  • 2018-03-10
  • 2016-05-14
相关资源
最近更新 更多