2

I was surprised, that SelectedIndexChanged on a ComboBox with ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList can be bypassed by changing the shown value to another one.

Here are steps to reproduce the case:

  • Create a Form with a ComboBox with ComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownListand some other control, which can get the focus (e.g. TextBox)
  • Attach an event handler for ComboBox.SelectedIndexChanged and let say do reset the selected index of ComboBox there always to 0 for only first entry could be selected.
  • Fill ComboBox.Items with e.g. integers from 1 to 5.
  • Start the application and open drop down list
  • Click any entry except the first and hold left mouse button down(no LMBUp must be triggered)
  • Press TAB key holding the left mouse button down
  • Clicked value is shown in the ComboBox and no ComboBox.SelectedIndexChanged being triggered.

What would be your offer to prevent this undesirable behavior. Tab key must not be suppressed and ComboBox.SelectedIndexChanged must be triggered on change.

Some code for copy-paste:

public Form1()
{
    InitializeComponent();

    comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
    comboBox1.Items.Add(1);
    comboBox1.Items.Add(2);
    comboBox1.Items.Add(3);
    comboBox1.Items.Add(4);
    comboBox1.Items.Add(5);
    
    comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;
}
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    comboBox1.SelectedIndex = 0;
}
Rekshino
  • 6,954
  • 2
  • 19
  • 44
  • Indeed the event is ignored: the selection is modified and the focus passes to the next control. Any breakpoint is ignored. –  Jun 08 '21 at 18:02
  • @OlivierRogier selection changed or text changed? Can we verify current selected index? Can we test if `selectedItemchanged` fired or not? – T.S. Jun 08 '21 at 18:06
  • Does this answer your question? [WinForms ComboBox SelectedIndexChanged not firing when typing few chars followed by Alt+Down](https://stackoverflow.com/questions/4759579/winforms-combobox-selectedindexchanged-not-firing-when-typing-few-chars-followed) and [ComboBox SelectionChangeCommitted event doesn't work with AutoComplete](https://stackoverflow.com/questions/14488659/combobox-selectionchangecommitted-event-doesnt-work-with-autocomplete) –  Jun 08 '21 at 18:06
  • @T.S. The Selected index is changed, not only the text. – Rekshino Jun 08 '21 at 18:13
  • 1
    @OlivierRogier Thank you for the links, there the `ComboBoxStyle.DropDown` be discussed, but I got a solution with derived control. – Rekshino Jun 08 '21 at 18:24

2 Answers2

1

I have solved it with derived control:

class ModifiedComboBox : ComboBox
{
    private object _lastSelectedItem = null;

    protected override void OnDropDownClosed(EventArgs e)
    {
        if(SelectedItem != _lastSelectedItem)
        {
            OnSelectedIndexChanged(new EventArgs());
        }
        base.OnDropDownClosed(e);
    }

    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        _lastSelectedItem = SelectedItem;
        base.OnSelectedIndexChanged(e);
    }
}
Rekshino
  • 6,954
  • 2
  • 19
  • 44
0

It is unclear “why” you want this odd behavior from a ComboBox; however, it appears you did not look a little closer at the ComboBox events.

It is true what you describe... When the user presses the Tab key “while” still holding the mouse button on a selection in the combo box… then the ComboBoxes SelectedIndexChanged event does NOT fire since the control is still IN the process of “selecting” a different index.

However, the ComboBoxes Validating and Leave events DO fire in the above situation. Instead of creating another control for this, wiring up the combo boxes Validating or Leave event will fix what you describe. Something like…

The current SelectedIndexChanged for normal situations…

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
  comboBox1.SelectedIndexChanged -= new System.EventHandler(comboBox1_SelectedIndexChanged);
  comboBox1.SelectedIndex = 0;
  comboBox1.SelectedIndexChanged += new System.EventHandler(comboBox1_SelectedIndexChanged);
}

Then, using the ComboBoxes Leave event for the “special” case when the user Tabs out of the combo box.

private void comboBox1_Leave(object sender, EventArgs e) {
  comboBox1.SelectedIndexChanged -= new System.EventHandler(comboBox1_SelectedIndexChanged);
  comboBox1.SelectedIndex = 0;
  comboBox1.SelectedIndexChanged += new System.EventHandler(comboBox1_SelectedIndexChanged);
}
JohnG
  • 9,259
  • 2
  • 20
  • 29
  • Do you mean with _"odd behavior from ComboBox"_ resetting the index or that `SelectedInexChanged` event be fired on selection is changed? If the first, then context is preventing entry selection, which is used as kind of separator in the dropdownlist. For me it's clear bug in the control. – Rekshino Jun 09 '21 at 05:53
  • @Rekshino … _”…then context is preventing entry selection, which is used as kind of separator in the dropdownlist.”_ … ? … if the context is to “prevent entry selection”, then, why not simply disable the combo box? What context creates this particular situation? In addition, I am not sure if I agree with your term a “bug”. What is the combo box supposed to do? It is in the middle of “selecting” a new index and is kicked out “before” it can complete the operation and fire its events. – JohnG Jun 09 '21 at 06:19
  • Call it a “bug” if you like, however, the designers HAD to make a decision on what to do if the combo box lost focus WHILE it was in the middle of a selection change. They chose to keep the “currently” selected value. Not a bug, just a simple decision when the control loses focus during its operation. The designers had to pick one value over another. What you are calling a “bug” is more of a user problem. Use the control properly and problem solved. – JohnG Jun 09 '21 at 06:20
  • Only one/several entries must be disabled not complete combobox. "simple decision" - not to fire an event if change is occur?? And it doesn't matter whether the control has focus for firing the `SelectedIndexChanged` if selected index is changed, e.g. programmatically. – Rekshino Jun 09 '21 at 06:31
  • @Rekshino… _”Only one/several entries must be disabled not complete combobox.”_ … then filter the combo box items to show only the items you want when the user clicks on the combo box. – JohnG Jun 09 '21 at 06:56
  • _”"simple decision" - not to fire an event if change is occur??”_ … ? … from your description to re-create this… the “selection” is NEVER made. The user Tabs away before this is completed. – JohnG Jun 09 '21 at 06:57
  • _”And it doesn't matter whether the control has focus for firing the SelectedIndexChanged if selected index is changed, e.g. programmatically”_ …? … but this is NOT what you describe. The user is doing this Tab away action before they have “selected” a combo box value. Changing the index programmatically has nothing to do with what you describe. – JohnG Jun 09 '21 at 06:57
  • I am just saying that what you describe as a “bug” is more along the lines of what the designers decided to do when this happens. They MUST decide something and unfortunately it is different than what you want. If the user chooses to Tab away “before” making a selection in the combo box, then the user is not completing this action. What you are calling a bug, is simply the USER not using the control properly. – JohnG Jun 09 '21 at 06:58
  • I do not want to argue this and if you want to call it a bug, then so be it. – JohnG Jun 09 '21 at 06:58