ComboBox SelectionChangeCommitted event doesn't work with AutoComplete

Here is a short program that reproduces the problem I just encountered. This was compiled under MS Windows 7 with .NET 4.0, just in case that makes a difference.

using System;
using System.Drawing;
using System.Windows.Forms;

// Compile with "csc /target:exe /out:comboboxbug.exe /r:System.dll /r:System.Drawing.dll /r:System.Windows.Forms.dll comboboxbug.cs"
// in a Visual Studio command prompt.

static class Program
{
    [STAThread]
    static void Main()
    {
        //Create a label.
        Label oLabel = new Label();
        oLabel.Location = new Point (10, 10);
        oLabel.Size = new Size (100, 15);
        oLabel.Text = "Combo box bug:";

        // Create a combo-box.
        ComboBox oComboBox = new ComboBox();
        oComboBox.Location = new Point (10, 50);
        oComboBox.Size = new Size (150, 21);
        oComboBox.Items.AddRange (new object[]
            { "A", "A B", "A C", "A B C", "A C B", "A B C D", "A C B D" });
        oComboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        oComboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
        oComboBox.SelectionChangeCommitted
            += new EventHandler (comboBox_SelectionChangeCommitted);

        // Create a form.
        Form oForm = new Form();
        oForm.Size = new Size (200, 150);
        oForm.Controls.Add (oLabel);
        oForm.Controls.Add (oComboBox);

        // Run this form.
        Application.Run (oForm);
    }
    static void comboBox_SelectionChangeCommitted (object sender,
        EventArgs e)
    {
        MessageBox.Show ("SelectionChangeCommitted");
    }
}

Click in the text portion of the combo-box and type "A". You will get a list of autocomplete suggestions. Click one of the selections with your mouse. The SelectionChangeCommitted event doesn't happen!

Select a menu-item without using autocomplete. You'll get a message-box showing that the SelectionChangeCommitted event happened!

Given that the selection was changed by the user in both cases, shouldn't SelectionChangeCommitted be called in both cases?

Using the SelectedIndexChanged event is not an option, because for the application behind this canned example, I only want it to happen when the user makes a selection, not when it's set programmatically.


Using the SelectedIndexChanged event is not an option, because for the application behind this canned example, I only want it to happen when the user makes a selection, not when it's set programmatically.

You could also accomplish this by writing a wrapper method for changing the selection that temporarily disables your event.

Unfortunately I do not know off hand a solution to the issue that SelectionChangeCommitted not being started for the more general case (such as where you don't control the ComboBox or how it is accessed).

EDIT:

I made a streamer of all the events that ComboBox calls, and it doesn't appear that any other event will do what you are looking for. The only solution I can think of would involve hooking into the events that the AutoComplete triggers. The difficulty is knowing what those events are, since they don't appear to trigger off the ComboBox from what my minor testing shows.


FYI, here was the best solution I ever came up with. Obviously, this is a Leave event-handler on a ComboBox subclass. The SelectionChangeCommitted event doesn't happen on the mouse-click, but at least it happens during the normal flow of GUI interaction.

private void this_Leave (object sender, EventArgs e)
{
    // If this is an autocomplete combo-box, select the
    // item that was found by autocomplete.
    // This seems like something that ComboBox should be
    // doing automatically...I wonder why it doesn't?
    if (this.AutoCompleteMode != AutoCompleteMode.None)
    {
        // Determine which combo-box item matches the text.
        // Since IndexOf() is case-sensitive, do our own
        // search.
        int iIndex = -1;
        string strText = this.Text;
        ComboBox.ObjectCollection lstItems = this.Items;
        int iCount = lstItems.Count;
        for (int i = 0; i < iCount; ++i)
        {
            string strItem = lstItems[i].ToString();
            if (string.Compare (strText, strItem, true) == 0)
            {
                iIndex = i;
                break;
            }
        }

        // If there's a match, and this isn't already the
        // selected item, make it the selected item.
        //
        // Force a selection-change-committed event, since
        // the autocomplete was driven by the user.
        if (iIndex >= 0
        && this.SelectedIndex != iIndex)
        {
            this.SelectedIndex = iIndex;
            OnSelectionChangeCommitted (EventArgs.Empty);
        }
    }
}

If someone got this problem, I suggest a solution that works fine to me...

Think with me, to accept the suggest of Combo-box, generally the user needs to key down with an Enter key.

You can write into KeyDown event of Combo-box property, something like this:

    private void cboProperty_SelectionChangeCommitted(object sender, EventArgs e)
    {
       //Call here the event of SelectionChangeCommitted
       cboProperty_SelectionChangeCommitted(sender,null);
    }

It will raise the SelectionChangeCommitted on the right time.

链接地址: http://www.djcxy.com/p/11764.html

上一篇: 限制玻尔兹曼机器和深度学习的Java代码

下一篇: ComboBox SelectionChangeCommitted事件不适用于AutoComplete