繁体   English   中英

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

[英]How do I ignore simple events firing when changing control states in C# Windows Forms?

I'm creating a simple form in C# Windows Forms and run into a common situation where one control can alter the state of another, but both controls' events trigger some other method.

例如,考虑一个CheckboxNumericUpDown ,其中 state 或任何一个的值都应该触发重绘。 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()触发两次。

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

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

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

对于更一般的情况,如果控件之间有复杂的关系,则可以通过检查其自己的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();
}

这样,每个 object 都只依赖于自己。

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

只需移动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();
}

您可以在“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);

}

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

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

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

如果我记错了,请投反对票。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM