3

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

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

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

任何帮助将不胜感激。

4

4 回答 4

2

如果方法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;
}

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

于 2013-05-29T18:36:24.880 回答
2

只需在类中使用布尔值守卫来检查您是否在更新方法中。当您更新时,所有从 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;
    }        
}
于 2013-05-29T18:40:26.217 回答
2

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

于 2013-05-29T18:41:19.207 回答
1

我喜欢 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;
}
于 2013-05-29T18:53:08.977 回答