【问题标题】:Avoid cascading actions on PropertyChanged避免对 PropertyChanged 进行级联操作
【发布时间】:2014-08-15 13:40:58
【问题描述】:

假设我有这个模型:

public sealed class Model : ModelBase // base is a INotifyPropertyChanged implementation
{        
    private void SomeAction()
    {
        Console.WriteLine("SomeAction!");
    }

    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);

        switch (propertyName)
        {
            case "A":
                B = A + 1;
                SomeAction();
                break;
            case "B":
                SomeAction();
                break;
        }
    }

    public int A
    {
        get { return a; }
        set
        {
            if (a != value)
            {
                a = value;
                OnPropertyChanged("A");
            }
        }
    }
    private int a;

    public int B
    {
        get { return b; }
        set
        {
            if (b != value)
            {
                b = value;
                OnPropertyChanged("B");
            }
        }
    }
    private int b;      
}

这里有两个属性:ABB 取决于 A - 当 A 的值发生变化时,B 也必须更改。无论如何,当这些属性中的任何一个发生变化时,都应该执行SomeAction

显然,当A 更改时,我想避免两次调用SomeAction
有什么优雅的方式来做到这一点(某种布尔标志不是优雅的方式)?

UPD

我应该提到,我可能正在寻找比以下答案中提供的更通用的解决方案。原因是当属性数量增加时,代码复杂度增长得更快。例如,这些图 - D C A -> B - 将导致代码不易维护。

【问题讨论】:

    标签: c# .net inotifypropertychanged


    【解决方案1】:

    您可以在每个属性设置器中调用SomeAction

    public int A
    {
        get { return a; }
        set
        {
            if (a != value)
            {
                a = value;
                b = value + 1;
                OnPropertyChanged("A");
                OnPropertyChanged("B");
                SomeAction();
            }
        }
    }
    private int a;
    
    public int B
    {
        get { return b; }
        set
        {
            if (b != value)
            {
                b = value;
                OnPropertyChanged("B");
                SomeAction();
            }
        }
    }
    private int b;      
    

    【讨论】:

    • 由于属性设置器B = value + 1;,这仍然会调用SomeAction两次
    • @SriramSakthivel 是的,我刚刚注意到并进行了回滚。
    • 这看起来不错,+1
    • @Henrik:感谢您的回答。问题是您的代码避免了SomeAction 的重复调用,但它通常不能解决任务。如果有 3 或 4 个属性,或者依赖关系图会稍微复杂一点,你会怎么做?
    【解决方案2】:
        switch (propertyName)
        {
            case "A":
                //Change the Private b instead of B so it won't call SomeAction twice.
                b = A + 1;
                SomeAction();
                break;
            case "B":
                SomeAction();
                break;
        }
    

    【讨论】:

    • -1 错了。您已更改 b 的值,但未触发 PropertyChanged 事件。任何有界属性都不会更新。
    【解决方案3】:

    您是否将多个属性更改视为单个操作的标准似乎是:“它是否在OnPropertyChanged 方法中处理?”但也是这个方法首先单独负​​责调用动作,所以......为什么不设计OnPropertyChanged来避免级联呢?它应该像删除其中一个调用一样简单:

    case "A":
        B = A + 1;
        break;
    case "B":
        SomeAction();
        break;
    

    我不认为这是不优雅的,因为所有逻辑都本地化为一个方法。您基本上在这里有一个递归方法,其中“B”是终止条件。

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 2012-04-14
      • 1970-01-01
      • 2012-04-11
      相关资源
      最近更新 更多