【问题标题】:PropertyChanged affecting several propertiesPropertyChanged 影响几个属性
【发布时间】:2009-12-28 01:07:52
【问题描述】:

我有一种情况,我有几个变量的值相互依赖,如下所示:

A 是 B 和 C 的函数 B 是 A 和 C 的函数 C 是 A 和 B 的函数

任何一个值都可以在 UI 上更改。我正在做这样的计算和更改通知:

private string _valA;
private string _valB;
private string _valC;

public string ValA
{
    get { return _valA; }
    set
    {
        if (_valA != value)
        {
            _valA = value;
            RecalculateValues("ValA");       //Here ValB and ValC are calculated
            OnPropertyChanged("ValA");
        }
    }
}

public string ValB
{
    get { return _valB; }
    set
    {
        if (_valB != value)
        {
            _valB = value;
            RecalculateValues("ValB");       //Here ValA and ValC are calculated
            OnPropertyChanged("ValB");
        }
    }
}

(...)

private void RecalculateValues(string PropName)
{
    if (PropName == "ValA")
    {
       _valB = TotalValue * _valA;
       OnPropertyChanged("ValB");

       _valC = something * _valA
       OnPropertyChanged("ValC");
    }
    else
    (...)

}

我在更改变量的 setter 上调用计算方法,计算 _valB、_valC 的值(例如),然后为这些值调用 PropertyChanged。 我这样做是因为变量之间的依赖关系,像这样我可以控制使用正确值计算哪个变量。我还考虑过为其他变量触发 PropertyChanged 并对变量的 getter 执行计算,但我必须知道之前更改了哪个属性并使用该值......不确定它是否是最好/最简单的解决方案。

这是一个好方法吗?我不喜欢在 setter 块上执行此操作的想法,但当时我看不到任何更好的方法。您是否看到任何其他(更好或更清洁的解决方案)?

我遇到的另一个问题是使用 IdataErrorInfo 验证/向 UI 呈现错误信息。问题是 this[columnName] 索引器在设置器的末尾被调用,我需要在计算之前验证值,这样如果输入的值无效,则不会发生计算。我正在认真考虑放弃 IDataErrorInfo 并在计算发生之前简单地调用我的验证方法。有什么方法可以显式调用它或在值属性之后立即调用它?

注意:ValidationRules 不是一个选项,因为我需要从我的 ViewModel 调用另一个对象的验证逻辑。

【问题讨论】:

  • 您将_valA 等输入为字符串,但您在_valB = TotalValue * _valA 中对字符串执行“乘法”。请解释一下。

标签: c# wpf inotifypropertychanged idataerrorinfo


【解决方案1】:

可以在 Setter 中调用您的验证和计算,只要它不阻塞线程并进入繁重的 CPU 密集型计算。如果你有简单的 5 到 10 个基于数学的语句,而不涉及复杂的循环,那没关系。

对于数据绑定和 WPF,这是唯一的方法,但是还有一个称为 IEditableObject 的实现,它具有 BeginEdit、CancelEdit 和 EndEdit,您可以在其中对“EndEdit”函数进行计算和验证。

在 BeginEdit 中,您可以将所有值保存在临时存储中,在 CancelEdit 中,您可以从 temp 中取回所有值并为所有已修改的值触发 PropertyChaged 事件,在 EndEdit 中,您最终可以更新所有变量并触发 PropertyChanged所有这些都已更新。

IEditableObject 在性能方面是最好的,但在取消或结束之前它可能不会显示新值,但是立即显示的唯一方法就是你正在做的事情。

如果 cpu 使用率很高,您可以调用另一个线程来进行计算并设置变量,最后您可以触发 PropertyChanged,但是从技术上讲,您只是在做同样的事情,同时在 setter 中异步设置值。

【讨论】:

    【解决方案2】:

    由于您可以从类中的任何位置调用 NotifyPropertyChanged,简化此操作的一种方法是让您的 Calculate 方法为所有三个变量触发 NotifyPropertyChanged。当我有多重依赖的复杂计算时,我会使用这个技巧。有时您仍想在 Setter 中触发事件:在这种情况下,当我从 Calculations 中更新属性时,我使用标志字段来禁用事件,这样事件就不会被触发两次。

    【讨论】:

      猜你喜欢
      • 2011-09-25
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 2012-07-25
      • 2015-10-20
      相关资源
      最近更新 更多