自动更新控件的最佳方法是什么?

3
我有一个关于在.NET中更新控件的问题,希望能以这样一种方式进行更新:如果用户更新了一个字段,则另一个字段将自动更新一些数据,反之亦然。我正在使用两个NumericUpDown控件来转换一些数据。
我的问题是,我正在使用ValueChanged事件。由于这个原因,有时这些控件会陷入循环中,其中一个控件更新另一个控件,而另一个控件则试图更新第一个控件。结果有些随机。
那么,如何处理这种情况最好呢?简而言之,我只想在用户自己修改第一个控件时才更新另一个控件。
非常感谢任何帮助。

你是在问关于 WPF 还是 Silverlight? - John Saunders
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;
}

当然,这只是一个简单的例子(例如,它假设两个控件的值始终在变化。请根据您的情况进行适应)。

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;
    }        
}

1
这只是一场等待发生的灾难。你知道总有一天会有太多这样的标记,最终导致错综复杂的标记而意外地被留下设置,值不如预期地更新。请查看我的回应以获取更为健壮的方法。 - Tombala
@dohz Tombala说得对,这在简单情况下可以工作,但是你的控件不应该处理这个逻辑。我强烈建议你重新考虑。 - Andy

2
我建议您使用数据绑定并绑定到一个充当模型的对象。您的模型是更改其他值的逻辑所在的地方,基于属性的更改。该模型还会引发IPropertyChanged/IPropertyChanging事件,UI将会捕获这些事件。这不仅可以防止您描述的问题,而且如果您转移到其他内容(例如从WinForms到WPF或Asp.Net MVC),还可以将此业务逻辑保留在UI层之外。

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接