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

时间:2011-07-07 00:16:53

标签: c# winforms events

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

例如,考虑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(); } 是否已经存在。

以下是有问题的方法:

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; } 触发两次。

我的解决方法是引入一个布尔值,我可以有效地否定这种行为,但有时它会变得混乱:

{{1}}

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

4 个答案:

答案 0 :(得分: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();
}

这样,每个对象只依赖于自身。

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

答案 1 :(得分:1)

RedrawStuff();移至else子句。这种方式在两种情况下都被调用,但只有一次。

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    RedrawStuff();
}

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

答案 2 :(得分:1)

您可以在“RedrawStuff”方法的开头“取消连接”更改事件,并在最后再次连接它们。

private void RedrawStuff() { // un-wire the change events chkState.CheckedChanged -= new System.EventHandler(chkState_CheckedChanged); numStateValue.ValueChanged -= new System.EventHandler(chkState_CheckedChanged);

/* .... do you thing...including setting the state of both / either controls based on the state of things, without fear of triggering recursive changes... */ // wire them back up chkState.CheckedChanged += new System.EventHandler(chkState_CheckedChanged); numStateValue.ValueChanged += new System.EventHandler(chkState_CheckedChanged);

}

(我已经使用过这种方法几次,因为它似乎可以解决你所描述的问题,但如果有人要指出为什么我可能不理解的原因,我会很高兴这可能是一个糟糕的方法。)

答案 3 :(得分:1)

如果控件被禁用,我认为CheckedChanged上的CheckBox不会触发,所以这样做:

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

如果我记错了,就要投票了。