Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinForms ComboBox SelectedIndexChanged not firing when typing few chars followed by Alt+Down

In short

When I type a character in a ComboBox, press Alt+Down followed by Enter or Tab, the SelectedIndexChanged event doesn't fire, even though the SelectedIndex value does change! Why doesn't the event fire?

Update The same error occurs if you type a character, press Alt+Down and then type Esc. You would expect the Esc to cancel the change. However, the SelectedIndex does change, and the SelectedIndexChanged event doesn't fire.

What should happen if you just type Alt+Down, use the arrow keys to browse to an entry, and then type Esc? Should the selected index be set back to its original value?


Not so short

I have a WinForm application with a ComboBox on it. The ComboBox' SelectedIndexChanged event is wired up to a event handler that shows the SelectedItem in a Label control. The ComboBox' Items collection has three values: "One", "Two", and "Three".

  • When I select an item with the mouse, the event fires.
  • When I scroll the mouse, the event fires.
  • When I use Alt+Down to expand the combobox and walk through the items with Up and Down, the event fires.
  • But... When I type in the first character of a value, then press Alt+Down, followed by Enter or Tab, the value does get selected and is shown in the combobox, but the event doesn't fire.

I've also added a button that shows the SelectedIndex. It shows the SelectedIndex has changed. So even though the SelectedIndex does change, the SelectedIndexChanged event does not fire!

If I just type in a valid value like One the event doesn't fire either, but in that case a click on the button reveals the SelectedIndex indeed hasn't changed. So in that case the behavior is normal.


To reproduce, create a Form and add a ComboBox, a Label and a Button. Place the following code in the Form1.cs:

using System;
using System.Windows.Forms;

namespace ComboBoxSelectedIndexChanged
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            comboBox1.Items.AddRange(new object[] {
                "One",
                "Two",
                "Three"
            });
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            label1.Text = "Selected index: " + comboBox1.SelectedIndex;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Selected item: " + comboBox1.SelectedItem +
                "\nSelected index: " + comboBox1.SelectedIndex);
        }
    }
}
like image 531
comecme Avatar asked Jan 21 '11 13:01

comecme


People also ask

How do you stop a ComboBox SelectedIndexChanged event from firing when the form loads?

You can simply unbind the SelectedIndexChanged event, call your fill function and bind the SelectedIndexChanged event again.

How do I create a ComboBox drop-down?

You are allowed to style drop-down list in your ComboBox by using the DropDownStyle Property. The value of this property is provided by the ComboBoxStyle enumeration and the values are: Simple: In this style, the list is visible and the text can be editable.

How do I disable writing in ComboBox?

We can select any option in the dropdown list. Now add state = "readonly" in the Combobox object, it will make the Combobox Entry Widget disabled.

How do I make my ComboBox read only?

Just change the DropDownStyle to DropDownList . Or if you want it completely read only you can set Enabled = false , or if you don't like the look of that I sometimes have two controls, one readonly textbox and one combobox and then hide the combo and show the textbox if it should be completely readonly and vice versa.


1 Answers

I've tried several google searches in order to find a definitive answer on this but didn't find one before. Just now I found a thread that actually refers to a Microsoft knowledge base article about the problem. Article KB948869 describes the problem.

The knowledge base article suggest to create your own combobox and override the ProcessDialogKey method.

using System.Windows.Forms;

public class MyComboBox : ComboBox
{
    protected override bool ProcessDialogKey(Keys keyData)
    {
        if (keyData == Keys.Tab)
            this.DroppedDown = false;
        return base.ProcessDialogKey(keyData);
    }
}

I've tried it, but unfortunately, it doesn't seem to have any effect. Which is a bit strange. I would expect a workaround described in a knowledge base article to be accurate.

I found another workaround though, which is to use the DropDownClosed event in stead.

private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
    label1.Text = "DroDownClosed Selected index: " + comboBox1.SelectedIndex;
}

This does seem to work, but only when using DropDownStyle.DropDown. When you set the DropDownStyle to DropDownList, typing a character does not fire the DropDownClosed (as there is no actual drop down in that case). Only if you actually open up the drop down list and select a value the DropDownClosed event is fired.

So, both options are not really a good answer.

Update I've even tried overriding property SelectedIndex in MyComboBox, having it call OnSelectedIndexChanged(EventArgs.Empty). After typing a character and pressing Alt+Down, the setter is executed, but it's setting the value to -1, which it already is. After pressing Tab, the setter isn't executed again, although somehow the SelectedIndex value does change. It looks like the ComboBox is directly changing the backing field for SelectedIndex, bypassing the setting. I believe something like this probably also happens in the real ComboBox.

like image 113
comecme Avatar answered Oct 11 '22 02:10

comecme