我正在C# Windows窗体中创建一个简单的窗体,遇到了一种常见的情况,即一个控件可以更改另一个控件的状态,但两个控件的事件都触发了某个其他方法。
例如,考虑Checkbox
和NumericUpDown
,其中任何一个的状态或值都应该触发重绘。NumericUpDown
依赖于Checkbox
,这意味着它可以被禁用或忽略,除非选中Checkbox
。
但是,用户可以方便地更改NumericUpDown
值,并自动检查Checkbox
(如果尚未检查)。
下面是一些有问题的方法:
private void chkState_CheckedChanged(object sender, EventArgs e)
{
RedrawStuff();
}
private void numStateValue_ValueChanged(object sender, EventArgs e)
{
if (!chkState.Checked)
chkState.Checked = true;
RedrawStuff();
}
当然,问题是更改NumericUpDown
值会导致RedrawStuff()
触发两次。
我的解决方法是引入一个布尔值,在这里我可以有效地否定这种行为,但有时候会变得很混乱:
bool _preventStateChange;
private void chkState_CheckedChanged(object sender, EventArgs e)
{
if (_preventStateChange)
return;
RedrawStuff();
}
private void numStateValue_ValueChanged(object sender, EventArgs e)
{
_preventStateChange = true;
if (!chkState.Checked)
chkState.Checked = true;
RedrawStuff();
_preventStateChange = false;
}
这是处理这种情况的最好方法吗?
4条答案
按热度按时间dxxyhpgq1#
对于更一般的情况,如果控件之间有复杂的关系,则可以通过检查其自身的
Focused
属性来检查哪个控件触发了事件:这样,每个对象都只依赖于它自己。
据我所知,对象必须有焦点才能触发用户事件,并且在任何给定时间只能有一个对象有焦点。但是,我不确定它是否在所有情况下都能工作,所以这仍然需要测试。
js4nwp542#
只需将
RedrawStuff();
移到else子句中,这样它在两种情况下都会被调用,但只调用一次。vs91vp4v3#
您可以在“RedrawStuff”方法开始时“取消连接”change事件,并在结束时再次连接它们。
}
(我已经用过几次这种方法,因为它似乎能解决你所描述的问题,但如果有人能指出为什么,我可能不明白,它可能是一个坏的方法,我会很高兴。)
envsm3lx4#
我认为如果控件被禁用,
CheckBox
上的CheckedChanged
不会触发,因此执行以下操作: