2013-01-23 2 views
7

Вот короткая программа, которая воспроизводит проблему, с которой я столкнулся. Это было скомпилировано под MS Windows 7 с .NET 4.0, на всякий случай это имеет значение.ComboBox SelectionChangeCommitted событие не работает с автозаполнением

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». Вы получите список предложений автозаполнения. Выберите один из вариантов с помощью мыши. Событие SelectionChangeCommitted не происходит!

Выберите пункт меню без использования автозаполнения. Вы получите сообщение с сообщением о том, что произошло событие SelectionChangeCommitted!

Учитывая, что выбор был изменен пользователем в обоих случаях, не следует ли в обоих случаях вызывать SelectionChangeCommitted?

Использование события SelectedIndexChanged не является обязательным, поскольку для приложения, стоящего за этим законченным примером, я хочу только, чтобы это произошло, когда пользователь делает выбор, а не когда он установлен программно.

+0

Я пробовал ваш код, но все отлично. – spajce

+0

Любая возможность [эта проблема] (http://stackoverflow.com/questions/13291945/winforms-combobox-loses-autocomplete-value-on-lostfocus) вообще помогает? – Guvante

+0

@spajce: Я запустил исходный код примера, как написано, и продублировал описанное поведение. Win 8, VS 2010, .NET 4. Обратите внимание, что ожидаемое поведение появляется при выборе значения как части автоматического завершения. – Guvante

ответ

2

Использование SelectedIndexChanged события не вариант, потому что для применения за этого консервированным например, я только хочу, чтобы это произошло, когда пользователь делает выбор, а не когда это набор программно.

Вы также можете выполнить это, написав метод обертки для изменения выбора, который временно отключает ваше событие.

К сожалению, я не знаю, из-за проблемы с решением, что SelectionChangeCommitted не запускается для более общего случая (например, где вы не контролируете ComboBox или как он доступен).

EDIT:

Я сделал растяжку всех событий, которые COMBOBOX звонков, и это не кажется, что любое другое событие будет делать то, что вы ищете. Единственное решение, о котором я могу думать, связано с подключением к событиям, которые запускает автозаполнение. Трудность заключается в том, чтобы знать, что такое эти события, поскольку они, похоже, не вызывают ComboBox, что показывает мое незначительное тестирование.

1

FYI, вот лучшее решение, которое я когда-либо придумывал. Очевидно, что это обработчик события Leave в подклассе ComboBox. Событие SelectionChangeCommitted не происходит при щелчке мыши, но, по крайней мере, это происходит во время обычного потока взаимодействия с графическим интерфейсом.

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); 
     } 
    } 
} 
0

Если кто-то получил эту проблему, я предлагаю решение, которое отлично работает для меня ...

Подумайте со мной, чтобы принять внушал Combo коробки, как правило, пользователь должен ввести вниз клавишу Enter.

Вы можете написать в KeyDown случае Combo ящика собственности, что-то вроде этого:

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

Это поднимет SelectionChangeCommitted на нужное время.

+0

Пользователь может также начать работу с другой частью формы, а не с клавиатуры. Кроме того, вы вызываете свой метод 'cboProperty_SelectionChangeCommitted()'? Разве это не бесконечный цикл? – ulatekh

Смежные вопросы