11

My C# application has a comboBox with a SelectedIndexChanged event. Usually, I want this event to fire, but but sometimes I need the event to not fire. My comboBox is an MRU file list. If a file in the list is found to not exist, the item is removed from the comboBox, and the comboBox SelectedIndex is set to zero. However, setting the comboBox SelectedIndex to zero causes the SelectedIndexChanged event to fire, which in this case is problematic because it causes some UIF code to be run in the event handler. Is there a graceful way to disable/enable events for C# form controls? Thanks.

5 Answers 5

19

Start the eventhandler method with

ComboBox combo = sender as ComboBox;
if (combo.SelectedIndex == 0)
{
    return;
}

If you're issue is with a different eventhandler you could remove the eventhandler's event registration first.

combo.SelectedIndexChanged -= EventHandler<SelectedIndexChangedEventArgs> SomeEventHandler;
combo.SelectedIndex = 0;
combo.SelectedIndexChanged += EventHandler<SelectedIndexChangedEventArgs> SomeEventHandler;
Sign up to request clarification or add additional context in comments.

1 Comment

Is this still the broadly accepted way to prevent the event? [by removing and then re-adding after the 'triggering' action] Just seems like there should be a better way.
13

I have encountered this many times over the years. My solution is to have a class level variable called _noise and if I know I am about to change the index of combo or any other similiar control that fires when the selected index changes, I do the following in code.

private bool _noise;

Here is the code for the control event handler

private void cbTest_SelectedIndexChange(object sender, EventArgs e)
{
   if (_noise) return;

   // process the events code

   ...

}


Then when I know I am going to change the index, I do the following:

_noise = true; // cause the handler to ignore the noise...


cbTest.Index = value;


_noise = false;  // let the event process again

Comments

5

I'm surprised there isn't a better way of doing this, but this is the way I do it. I actually use the Tag field of most controls so I don't have to subclass the control. And I use true/null as the values, since null is the default.

Of course, if you are actually using Tag, you'll need to do it differently...

In handler:

 private void control_Event(object sender, EventArgs e)
 {
    if (control.Tag != null ) return;

    // process the events code

    ...

 }

In main code

 try 
 {
    control.Tag = true;
    // set the control property
    control.Value = xxx;
or
    control.Index = xxx; 
or
    control.Checked = xxx;
    ...
 }
 finally 
 {
    control.Tag = null;
 }

1 Comment

I like this solution more than a class scoped variable as this value is directly tied to the control in question making it a more robust solution considering if you had to do similar things with different controls (or even the same one) in multiple event handlers.
2

There's a better way!

combo_box = QComboBox() # your combobox
combo_box.blockSignals(True)
combo_box.setCurrentIndex(self, ix)
combo_box.blockSignals(False)
    

1 Comment

This does seem good. Can you add a little explanation of what this does better or what it is doing? For people who don't understand "blockSignals."
1

One (fairly ugly) way would be to set a flag in the code that deletes the entry and then check that in the SelectedIndexChanged handler:

if (!deletedEntry)
{
    // Do stuff
}
deletedEntry = false;

A better way might be to remove your SelectedIndexChanged event handler at the start of the delete method and reinstate it at the end. This way you code won't know the index has changed.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.