2009-12-18 6 views
1

У меня возникла ситуация, когда я хочу изменить выбранное значение поля со списком в приложении Windows Forms, используя Ctrl-Left ori Ctrl-Right. Однако, если combobox является выбранным элементом управления в форме, это не работает. Выбранное значение устанавливается на старое значение после того, как оно установлено на новое значение. Если combobox не является выбранным элементом управления, все работает нормально. В моем приложении комбо может получать фокус, потому что значения также могут быть изменены с помощью мыши. Хотя то, что я хочу, может быть достигнуто путем выбора какого-либо другого элемента управления в форме, прежде чем фактически изменить значение, которое мне не нравится в этом решении.C# combobox selected index changed fires old value

Итак, есть два вопроса: Почему событие selectedIndexChanged запускается со старым значением, если поле со списком является выбранным элементом управления в форме и Как это можно избежать или если я не могу найти подходящее обходное решение? Далее приведен код, иллюстрирующий мою проблему. Если вы снимете поле со списком и поле richtext в форме и скопируете приведенный ниже код в Form1.cs, вы можете увидеть мою проблему. Вам нужно сделать комбо DropDownList стиль и добавить некоторые цифры в качестве элементов (1, 2, 3 отлично)

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     comboBox1.SelectedIndex = 0; 
    } 

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == (Keys.Control | Keys.Left)) 
     { 
      DoUpdate(); 
     } 
     return base.ProcessCmdKey(ref msg, keyData); 
    } 

    private void DoUpdate() 
    { 
     int index = Convert.ToInt32(comboBox1.SelectedItem); 
     index++; 
     if (comboBox1.Focused) 
      richTextBox1.Select(); 
     comboBox1.SelectedItem = index.ToString(); 
    } 

    private void SetComboValue(int value) 
    { 
     comboBox1.SelectedItem = value.ToString(); 
     richTextBox1.AppendText(string.Format("Set value {0} \r\n", value.ToString()));   
    } 

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     richTextBox1.AppendText(string.Format("Selected index changed before {0}\r\n", comboBox1.SelectedItem)); 
     SetComboValue(Convert.ToInt32(comboBox1.SelectedItem)); 
     richTextBox1.AppendText(string.Format("Selected index changed after {0}\r\n", comboBox1.SelectedItem)); 
    } 
} 
+0

Что об использовании метода, чтобы получить соответствующий ему уровень индекса COMBOBOX: SelectedIndex. Это исправить? – RvdK

ответ

1

Это связано с тем, что по умолчанию, если в поле со списком имеется фокус, то нажатие влево и вправо (без управления) изменит значение.

Вы ловите ctrl-left, увеличивая значение ... и затем передавая нажатие клавиши базовому объекту, который интерпретирует левое нажатие и уменьшает выбранный элемент.

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

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == (Keys.Control | Keys.Left)) 
     { 
      DoUpdate(); 
      return true; 
     } 
     else 
     { 
      return base.ProcessCmdKey(ref msg, keyData); 
     } 
    } 
+0

Вы ужасно правы :-) Я был так сосредоточен на Ctrl-Left, что я прощал, что я нажимаю клавиши «Влево» и «Вправо», и они также будут действовать как курсор в выпадающем списке. Однако теперь у меня есть вопрос: если я верну эту истинную ценность в ProcessCmdKey, эта комбинация клавиш будет распространяться дальше на другие программы, которые «прослушивают» эти ключи или нет? У меня есть небольшое приложение, установленное на моем компьютере, и это что-то делает, когда я нажимаю Ctrl-M, но также как-то перестает распространять эту комбинацию клавиш (в результате Ctrl-M в VS ничего не сделает в этом конкретном случае) – mosu

+0

Я не уверен, какое поведение будет при прослушивании других приложений, но msdn говорит следующее: «При переопределении метода ProcessCmdKey в производном классе элемент управления должен возвращать true, чтобы указать, что он обработал ключ. не обрабатываются элементом управления, результат вызова метода ProcessCmdKey базового класса должен быть возвращен ». (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey.aspx) ... Так что я думаю, что это правильное действие? – rcknight

+0

Я обработал нажатой клавишу Shift, и это не значит, что проблема не вернется. После нажатия 5 раз появляется сообщение Windows StickyKeys, поэтому я думаю, что сообщение отправлено дальше. Большое спасибо за ответ. – mosu

0

Почему вы не просто запустить метод SetComboValue от вашего метода DoUpdate? Если это не сработает, вы всегда можете установить флаг, который устанавливает, что он установлен из метода DoUpdate, и только запускать выбранное событие с измененным индексом при прямом доступе. Просто мысль.

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

Моя мысль заключается в том, что вы устанавливаете значение, но что-то еще вызывает второе событие changeitem change. Однако похоже, что вы можете попасть в бесконечный цикл, поскольку вы устанавливаете выбранный индекс в методе DoUpdate и методе SetComboValue.

Просто измените выбранный индекс в одном месте.

+0

Благодарим вас за комментарий Джошуа. Это не изменит проблему, потому что в SetComboValue это строка: comboBox1.SelectedItem = value.ToString(); (на самом деле это был comboBox1.SelectedItem = Convert.ToInt32 (значение); , но я изменил это, потому что неверно), который еще раз вызовет событие selectedIndexChanged. Поэтому даже если я устанавливаю значение, даже если я вызываю метод для установки значения, у меня такая же проблема. Я не называю SetComboValue из-за соображений дизайна. Я думаю, что лучше иметь эту функцию, вызванную некоторыми другими методами. – mosu

+0

Я стараюсь не добавлять другую глобальную переменную, чтобы действовать как флаг, потому что у меня уже есть некоторые флаги, о которых нужно заботиться, и я не считаю это, в моем случае, хорошим дизайном. – mosu

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