在C#Windows窗体中更改控件状态时,如何忽略触发的简单事件?

JYe*_*ton 5 c# events winforms

我在C#Windows窗体中创建一个简单的表单并遇到一种常见的情况,一个控件可以改变另一个控件的状态,但两个控件的事件都会触发其他一些方法.

例如,考虑a CheckboxNumericUpDown其中任何一个的状态或值应触发重绘的内容.将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();
}
Run Code Online (Sandbox Code Playgroud)

问题当然是改变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;
}
Run Code Online (Sandbox Code Playgroud)

这是处理这种情况的最佳方法吗?

Yan*_*man 6

对于更一般的情况,如果控件之间有复杂的关系,您可以通过检查自己的Focused属性来检查哪个控件触发了事件:

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    if (chkState.Focused)
        RedrawStuff();
}

private void numStateValue_ValueChanged(object sender, EventArgs e)
{
    if (!chkState.Checked)
        chkState.Checked = true;

    if (numStateValue.Focused)
        RedrawStuff();
}
Run Code Online (Sandbox Code Playgroud)

这样,每个对象仅依赖于自身.

据我所知,该对象必须具有激发用户事件的焦点,并且在任何给定时间只能有一个具有焦点的对象.但是,我不确定它是否适用于所有情况,因此仍需要测试.