【问题标题】:Best way to handle controls automatically updating each other?处理控件自动相互更新的最佳方法?
【发布时间】:2013-05-30 02:53:08
【问题描述】:

我有一个关于在 .Net 中更新控件的问题,如果用户更新一个字段,另一个字段将自动更新一些数据,反之亦然。我正在使用两个 NumericUpDown 控件来转换一些数据。

我遇到的问题是,我正在使用 ValueChanged 事件。因此,有时这些控件会陷入循环,其中一个控件更新另一个控件,而另一个尝试更新第一个控件。结果有些随机。

那么,处理这种情况的最佳方法是什么?简而言之,如果第一个控件是由用户自己修改的,我只想更新另一个控件。

任何帮助将不胜感激。

【问题讨论】:

  • 您问的是 WPF 还是 Silverlight?

标签: c# .net


【解决方案1】:

只需在类中使用布尔值守卫来检查您是否在更新方法中。 在您进行更新时,所有未来从 NUD 触发的事件都将被忽略。

private boolean updating = false; // Class level variable

void event_handler(...) // The function hooked up to the ValueChanged event
{
    if( !updating )
    {
        updating = true;
        // Do your calculations and update the NUDs
        updating = false;
    }        
}

【讨论】:

  • 这简直就是一场等待发生的灾难。您知道在某个地方您将拥有太多这些标志,并且您最终会得到意大利面条式的标志,这些标志意外地被设置并且值没有按预期更新。请参阅我的回复以了解不那么脆弱的方法。
  • @dohz Tombala 是对的,这在简单的情况下会起作用,但实际上你的控件不应该处理这个逻辑。我强烈建议您重新考虑。
【解决方案2】:

我建议您使用数据绑定并绑定到用作模型的对象。然后,您的模型是根据属性更改更改其他值的逻辑所在。该模型还引发了 IPropertyChanged / IPropertyChanging 事件,UI 将接受这些事件。这不仅可以防止您描述的问题,而且如果您移动到其他东西(例如从 WinForms 到 WPF 或 Asp.Net MVC),它还会将此业务逻辑保留在您的 UI 层之外。

【讨论】:

    【解决方案3】:

    如果方法Foo 处理一个控件的事件,而方法Bar 处理另一个控件的事件,那么Foo 应该更改Bar 的控件的值,反之亦然。但是您应该在某处使用控制变量(例如,对触发事件的控件的引用是个好主意)。这样如果Foo 被调用:

    • Foo更新Bar的控件值;
    • Bar 的控件触发其事件,并调用 Bar
    • Bar 检查首先触发的控件的引用,发现它不是它的控件,因此什么也不做。

    同样的逻辑适用于Bar

    这样你就不会陷入无限循环。

    在代码中,它看起来像这样:

    nud1.ValueChanged += new Eventhandler(Foo);
    nud2.ValueChanged += new Eventhandler(Bar);
    NumericUpDown shooter = null;
    
    private void Foo (object sender, EventArgs e)
    {
        if (this.shooter == null)
        {
            this.shooter = nud1;
            nud2.Value = nud1.Value;
        }
        else this.shooter = null;
    }
    
    private void Bar (object sender, EventArgs e)
    {
        if (this.shooter == null)
        {
            this.shooter = nud2;
            nud1.Value = nud2.Value;
        }
        else this.shooter = null;
    }
    

    当然,这是一个粗略的例子(例如,它假设两个控件的值总是在变化。适应你的情况。

    【讨论】:

      【解决方案4】:

      我喜欢 Andy 关于采用 MVC 模式的回应,但如果对于这种特定情况而言,这种改变过于激进,那么只有在当前值与分配的值不同时才应设置值。这将防止 ValueChanged 事件再次触发,并在第一次发生递归时停止无限循环。

      // Inside your value changed handler for Control2,
      // instead of directly setting the value of Control1, do this:
      if(Control1.Value != valueBeingSet)
      {
          Control1.Value = valueBeingSet;
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 2022-11-27
        • 2011-03-21
        • 2017-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多