简体   繁体   中英

Issue in CheckedChanged event

I have a check box and I have subscribed for the CheckedChanged event. The handler does some operations in there. I check and uncheck the checkbox programmatically (ex: chkbx_Name.Checked = true ), and the CheckedChanged event gets fired.

I want this event to be fired only when I manually check or uncheck it. Is there any way to avoid firing of this event when i check/uncheck it programmatically?

unsubscribe the event before you set:

check1.CheckChanged -= check1_CheckChanged;

then you can programmatically set the value without the checkbox firing its CheckChanged event:

check1.Checked = true;

then re-subscribe:

check1.CheckChanged += check1_CheckChanged;

[EDIT: March 29, 2012]

The problem with Tanvi's approach is you need to catch all source of manual check or uncheck . Not that there's too many(it's only from mouse click and from user pressing spacebar), but you have to consider invoking a refactored event from MouseClick and KeyUp(detecting the spacebar)

It's more neat for a CheckBox(any control for that matter) to be agnostic of the source of user input(keyboard, mouse, etc), so for this I will just make the programmatic setting of CheckBox really programmatic. For example, you can wrap the programmatic setting of the property to an extension method:

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

Using this approach, your code can respond neatly to both user's mouse input and keyboard input via one event only, ie via CheckChanged. No duplication of code, no need to subscribe to multiple events (eg keyboard, checking/unchecking the CheckBox by pressing spacebar)

No. Those property change events fire whenever the property value changes, regardless of whether this was done by your code, by the control's own code or databinding. It's all the same code path, usually.

What you can do, however, if your event handler resides in the same class as the code that changes the property value, is to introduce a private boolean field in the class which you use as an indicator of whether the current property change is triggered by your code or by the user. After your change you simply reset it. The event handler would then look at the field and decide of whether it should do anything or not:

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

I'm sorry I can't just comment on Michael Buen's answer due to my being new here (no reputation), but for what it's worth I strongly prefer his solution to Johannes Rössel's for a couple of reasons.

1) the checkedProgrammatically variable is a little too close to global for me. There's nothing to stop another method accidentally setting it to true, causing all your events to stop.

2) you could end up with a lot of variables depending on the number of events you're dealing with. It would be easy to change the wrong one and the results can be difficult to debug.

3) it's more obvious what you're doing when you unsubscribe then resubscribe. All the logic is right there, and you don't need to change your event handlers to exit early depending on certain conditions.

I've used both methods extensively and I find Michael's a lot easier in the long run.

You can use the MouseClick event and in that check for the checked state of the checkbox. This way it wont be triggered programatically, it would only be called when the user manually checks or unchecks the checkbox.

您可以在以编程方式更改值之前设置布尔变量,并在checkedchanged事件中检查并重置该变量

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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