在CheckedChanged事件中存在问题

9

我有一个复选框并订阅了CheckedChanged事件。事件处理程序在其中执行一些操作。我通过编程方式选中和取消选中复选框(例如:chkbx_Name.Checked = true),然后触发了CheckedChanged事件。

我希望仅在手动选中或取消选中时触发此事件。是否有任何方法可以避免在编程方式下选中/取消选中时触发此事件?

5个回答

13

在设置之前取消订阅事件:

check1.CheckChanged -= check1_CheckChanged;

那么你可以以编程方式设置该值,而不触发复选框的 CheckChanged 事件:

check1.Checked = true;

然后重新订阅:

check1.CheckChanged += check1_CheckChanged;

[编辑:2012年3月29日]

Tanvi的方法存在问题,需要捕获所有手动勾选或取消勾选的源。虽然并不多(只有鼠标单击和用户按下空格键),但你必须考虑从MouseClick和KeyUp(检测空格键)调用重构后的事件。

对于CheckBox(或任何控件),更加优雅的做法是对用户输入的来源(键盘、鼠标等)保持不可知性,因此我将使CheckBox属性的编程设置真正成为编程。例如,您可以将属性的编程设置封装到扩展方法中:

static class Helper
{
    public static void SetCheckProgrammatically(
        this CheckBox c, 
        EventHandler subscribedEvent, bool b)
    {            
        c.CheckedChanged -= subscribedEvent; // unsubscribe
        c.Checked = b;
        c.CheckedChanged += subscribedEvent; // subscribe
    }
}
使用这种方法,您的代码可以通过一个事件(即CheckChanged)整洁地响应用户的鼠标输入和键盘输入,无需重复代码,无需订阅多个事件(例如键盘,通过按空格键选中/取消选中复选框)。

我喜欢这个解决方案,但如果在一个项目中有多个程序员,那么每次更改此属性时,每个人都必须取消订阅吗? - Paul C
将其包装在扩展属性中,嗯...扩展方法。例如,check1.SetCheckedRaw(booleanHere)。 - Michael Buen

5
不会。这些属性更改事件在属性值更改时触发,无论是您的代码、控件自己的代码还是数据绑定完成的。通常情况下,它们都是相同的代码路径。
但是,如果您的事件处理程序与更改属性值的代码位于同一类中,则可以引入一个私有布尔字段作为指示当前属性更改是由您的代码还是用户触发的指示器。更改后,您只需重置它。然后,事件处理程序将查看该字段并决定是否应执行任何操作。
class Foo : Form {
    private bool checkedProgrammatically = false;

    void someMethod() {
        // ...
        checkedProgrammatically = true;
        checkBox1.Checked = true;
        checkedProgrammatically = false;
        // ...
    }

    private void checkBox1_CheckChanged(object sender, EventArgs e) {
        if (checkedProgrammatically) return;
        // ...
    }
}

1

很抱歉,由于我在这里还是新手(没有声望),所以不能仅仅评论Michael Buen的答案,但就其价值而言,我强烈倾向于他的解决方案,原因如下:

1)checkedProgrammatically变量对我来说有点太接近全局了。没有任何方法可以阻止另一个方法意外将其设置为true,导致所有事件停止。

2)根据您处理的事件数量,您可能会得到许多变量。更改错误的变量很容易,结果可能难以调试。

3)取消订阅然后重新订阅时,您正在做什么更加明显。所有逻辑都在那里,您不需要根据某些条件提前更改事件处理程序。

我已经广泛使用了这两种方法,我发现Michael的方法在长期运行中更容易。


1
你可以使用MouseClick事件,在其中检查复选框的选中状态。这样它就不会被程序触发,只有当用户手动选中或取消选中复选框时才会调用它。

1
如果用户通过空格键而不是鼠标选中/取消复选框,会发生什么?请查看我的解决方案。 - Michael Buen

0

在程序中改变值之前,您可以设置布尔变量,并在CheckedChanged事件中检查和重置该变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接