我有一个关于更新 .Net 中的控件的问题,如果用户更新一个字段,另一个字段将自动更新一些数据,反之亦然。我正在使用两个 NumericUpDown 控件来转换一些数据。
我遇到的问题是,我正在使用 ValueChanged 事件。因此,有时这些控件会陷入循环,其中一个控件更新另一个控件,而另一个尝试更新第一个控件。结果有些随机。
那么,处理这种情况的最佳方法是什么?简而言之,我只想更新另一个控件,如果第一个控件是由用户自己修改的。
任何帮助将不胜感激。
如果方法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;
}
当然,这是一个粗略的例子(例如,它假设两个控件的值总是在变化。适应你的情况。
只需在类中使用布尔值守卫来检查您是否在更新方法中。当您更新时,所有从 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;
}
}
我建议您使用数据绑定并绑定到用作模型的对象。然后,您的模型是根据属性更改更改其他值的逻辑所在。该模型还引发了 IPropertyChanged / IPropertyChanging 事件,UI 将接受这些事件。这不仅会阻止您描述的问题,而且如果您移动到其他东西(例如从 WinForms 到 WPF 或 Asp.Net MVC),它还会将此业务逻辑保留在您的 UI 层之外。
我喜欢 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;
}