8

これは、私が遭遇した問題を再現する短いプログラムです。これは、違いが生じる場合に備えて、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");
    }
}

コンボ ボックスのテキスト部分をクリックし、「A」と入力します。オートコンプリート候補のリストが表示されます。選択項目の 1 つをマウスでクリックします。イベントはSelectionChangeCommitted発生しません!

オートコンプリートを使用せずにメニュー項目を選択します。SelectionChangeCommittedイベントが発生したことを示すメッセージ ボックスが表示されます。

どちらの場合もユーザーによって選択が変更された場合、両方の場合でSelectionChangeCommitted呼び出されるべきではありませんか?

この缶詰の例の背後にあるアプリケーションでは、プログラムで設定されたときではなく、ユーザーが選択を行ったときにのみイベントが発生するようにするため、イベントの使用はSelectedIndexChangedオプションではありません。

編集 2020-Oct-28:SelectionChangeCommitted呼び出されない別のケースを見つけました! 問題が発生するためにオートコンプリートを設定する必要さえありません! クリックしてコンボ ボックスを開き、コンボ ボックス項目の 1 つの先頭に一致するキーを押してから、Tab キーを押して終了します。コンボ ボックスの項目が選択されますが、SelectionChangeCommitted呼び出されません! 私の修正された答えは以下です。

4

5 に答える 5

3

この缶詰の例の背後にあるアプリケーションでは、プログラムで設定されたときではなく、ユーザーが選択を行ったときにのみイベントが発生するようにするため、イベントを使用するSelectedIndexChangedことはオプションではありません。

イベントを一時的に無効にする選択を変更するためのラッパー メソッドを記述することによって、これを実現することもできます。

SelectionChangeCommitted残念ながら、より一般的なケース ( を制御していない場合ComboBoxやアクセス方法など) で開始されないという問題の解決策はわかりません。

編集:

ComboBox が呼び出すすべてのイベントのストリーマーを作成しましたが、探していることを実行する他のイベントはないようです。私が考えることができる唯一の解決策は、オートコンプリートがトリガーするイベントにフックすることです。難しいのは、それらのイベントが何であるかを知ることです。なぜなら、それらはComboBox私のマイナーなテストが示しているものからトリガーされているようには見えないからです.

于 2013-01-23T20:36:20.290 に答える
1

参考までに、これが私が思いついた最高の解決策です。明らかに、これは ComboBox サブクラスの Leave イベント ハンドラです。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);
        }
    }
}
于 2015-11-10T15:57:53.923 に答える