简体   繁体   English

ComboBox SelectionChangeCommitted 事件不适用于自动完成

[英]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.这是在 MS Windows 7 和 .NET 4.0 下编译的,以防万一。

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".单击组合框的文本部分并键入“A”。 You will get a list of autocomplete suggestions.您将获得自动完成建议的列表。 Click one of the selections with your mouse.用鼠标单击其中一个选项。 The SelectionChangeCommitted event doesn't happen! SelectionChangeCommitted事件不会发生!

Select a menu-item without using autocomplete.在不使用自动完成功能的情况下选择菜单项。 You'll get a message-box showing that the SelectionChangeCommitted event happened!您将收到一个消息框,显示SelectionChangeCommitted事件发生了!

Given that the selection was changed by the user in both cases, shouldn't SelectionChangeCommitted be called in both cases?鉴于用户在两种情况下都更改了选择,在两种情况下都不应该调用SelectionChangeCommitted吗?

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.使用SelectedIndexChanged事件不是一个选项,因为对于这个罐头示例背后的应用程序,我只希望它在用户进行选择时发生,而不是在以编程方式设置时发生。

EDIT 2020-Oct-28: I found another case where SelectionChangeCommitted doesn't get called!编辑 2020 年 10 月 28 日:我发现了另一个没有调用SelectionChangeCommitted情况! Auto-complete doesn't even need to be set for the problem to happen!甚至不需要设置自动完成即可发生问题! Click to open the combo-box, press a key that matches the beginning of one of the combo-box items, and then press Tab to leave.单击以打开组合框,按与组合框项目之一的开头匹配的键,然后按 Tab 键离开。 The combo-box item gets selected, but SelectionChangeCommitted is not called!组合框项目被选中,但没有调用SelectionChangeCommitted My revised answer is below.我修改后的答案如下。

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.使用SelectedIndexChanged事件不是一个选项,因为对于这个罐头示例背后的应用程序,我只希望它在用户进行选择时发生,而不是在以编程方式设置时发生。

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).不幸的是,我不知道对于更一般的情况(例如,您不控制ComboBox或如何访问它)没有启动SelectionChangeCommitted问题的解决方案。

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.我制作了 ComboBox 调用的所有事件的流光,并且似乎没有任何其他事件可以执行您正在寻找的操作。 The only solution I can think of would involve hooking into the events that the AutoComplete triggers.我能想到的唯一解决方案是挂钩 AutoComplete 触发的事件。 The difficulty is knowing what those events are, since they don't appear to trigger off the ComboBox from what my minor testing shows.困难在于知道这些事件是什么,因为从我的小测试显示,它们似乎不会触发ComboBox

FYI, here was the best solution I ever came up with.仅供参考,这是我想出的最佳解决方案。 Obviously, this is a Leave event-handler on a ComboBox subclass.显然,这是 ComboBox 子类上的 Leave 事件处理程序。 The SelectionChangeCommitted event doesn't happen on the mouse-click, but at least it happens during the normal flow of GUI interaction. SelectionChangeCommitted 事件不会在鼠标单击时发生,但至少在 GUI 交互的正常流程中会发生。

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.跟我想一想,要接受Combo-box的建议,一般用户需要按回车键。

You can write into KeyDown event of Combo-box property, something like this:您可以写入 Combo-box 属性的 KeyDown 事件,如下所示:

    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.它将在正确的时间引发 SelectionChangeCommitted 。

This workaround worked fine for me and hope for you too.这个解决方法对我来说很好,也希望对你有用。 When use Autocomplete by typing data in your combo box to get an item through keyboard or mouse selection you need _KeyDown event.当通过在组合框中键入数据使用自动完成功能以通过键盘或鼠标选择获取项目时,您需要 _KeyDown 事件。 From inside invoke _SelectionChangeCommitted method which contains code for other operations.从内部调用 _SelectionChangeCommitted 方法,该方法包含其他操作的代码。 See code below:见下面的代码:

    private void YourComboBox_KeyDown(object sender, KeyEventArgs e)
    {
        //Works also when user select and click on autocomplete list.
        if (e.KeyCode == Keys.Enter && YourComboBox.SelectedItem != null)
            YourComboBox_SelectionChangeCommitted(sender, e);
    }

For the non-auto-complete case mentioned above (ie my 2020-Oct-28 edit), this Leave event-handler on a ComboBox subclass incorporates the new case as well as the old one, as long as your SelectionChangeCommitted event-handler is idempotent .对于上面提到的非自动完成案例(即我的 2020 年 10 月 28 日编辑), ComboBox子类上的这个Leave事件处理程序包含新案例和旧案例,只要您的SelectionChangeCommitted事件处理程序是幂等的 Compared to my previous answer, it removes the test for auto-complete, and always calls OnSelectionChangeCommitted() .与我之前的答案相比,它删除了自动完成测试,并始终调用OnSelectionChangeCommitted()

private void this_Leave (object sender, EventArgs e)
{
    // 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.
    if (iIndex >= 0
    && this.SelectedIndex != iIndex)
        this.SelectedIndex = iIndex;

    // Force a selection-change-committed event, since
    // the autocomplete was driven by the user.
    OnSelectionChangeCommitted (EventArgs.Empty);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Combobox SelectionChangeCommitted事件不适用于箭头键 - Combobox SelectionChangeCommitted event doesn't work with arrow keys 组合框自动完成功能不起作用 - combobox Autocomplete doesn't work ComboBox在SelectionChangeCommitted上获得了新的SelectedValue,但没有新的SelectedText - ComboBox got new SelectedValue on SelectionChangeCommitted but doesn't got new SelectedText 从源代码触发ComboBox的SelectionChangeCommitted事件 - Trigger SelectionChangeCommitted event for ComboBox from source code 为ComboBox数组的事件“ SelectionChangeCommitted”创建一个空白 - Creating a void for the event “SelectionChangeCommitted” for a ComboBox array 使用DataGridView Combobox的SelectionChangeCommitted Event获取新值或索引 - Get the new value or index with SelectionChangeCommitted Event of DataGridView Combobox 打开 ComboBox 时 KeyDown 事件不起作用? - KeyDown event doesn't work when ComboBox is opened? 鼠标滚轮事件不适用于选项卡页上的组合框吗? - Mouse wheel event doesn't work for combobox on tab page? Winforms-组合框自动完成功能不显示具有相同名称的项目 - Winforms - Combobox autocomplete doesn't show items with the same name ComboBox SelectedValue属性不起作用 - ComboBox SelectedValue property doesn't work
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM