2013-03-19 2 views
1

Я программирую калькулятор на C#, и я пытаюсь добавить к нему ввод с клавиатуры. Проблема в том, что если я нажму кнопку на GUI, тогда клавиша Enter/Return будет сфокусирована на этом. Когда нажата клавиша возврата, она снова нажимает этот ключ, а не обрабатывается обработчиком событий KeyDown. Как я могу это исправить?Keyboard Input Return Key

private void Window_KeyDown(object sender, KeyEventArgs e) 
    { 
     switch (e.Key) 
     { 
      case Key.NumPad1: 
      case Key.D1: 
       addInput('1'); 
       break; 
      case Key.Return: 
       MessageBox.Show("Enter!"); 
       break; 
     } 
    } 
+1

показать нам, что вы пытались – Fredrik

+0

добавили код обработчика событий. – Emrys90

+2

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

1

Вы должны обрабатывать PreviewKeyDown событие вашей формы. Затем проверьте, хотите ли вы обработать событие, и если да, установите Handled свойство события true после того, как вы это сделаете.

Это вероятно, будет выглядеть примерно так:

public MainWindow() 
{ 
    InitializeComponent(); 

    PreviewKeyDown += new KeyEventHandler(MainWindow_PreviewKeyDown); 
} 

void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Space) 
    { 
     Log("Intercepted space in preview"); 
     e.Handled = true; 
    } 
} 

Почему вам нужно установить Handled в true? События в WPF запускаются на нескольких элементах пользовательского интерфейса, что зависит от его стратегии «» ». Когда ваш обработчик событий устанавливает Handled в true, видимость этого события будет ограничена другими элементами пользовательского интерфейса. Вскоре это не будет срабатывать в других элементах пользовательского интерфейса. Чтобы узнать больше о деталях решения выше, прочитайте остальную часть ответа ниже.


Есть некоторые вещи, которые вам необходимо понять, если вы хотите правильно использовать события в WPF. События присоединяются к элементам пользовательского интерфейса (текстовые поля, кнопки и т. Д.), А обработчики событий могут быть подключены к этим элементам пользовательского интерфейса. Кроме того, элементы пользовательского интерфейса организованы в древовидную структуру. Каждый элемент имеет свой родительский элемент, вплоть до корневого элемента пользовательского интерфейса. Как уже упоминалось, события срабатывают по нескольким элементам в зависимости от их стратегии маршрутизации ". Несколько элементов здесь означают элемент, на который нацелено событие, и его родители, вплоть до корневого элемента. Событие стратегии маршрутизации может быть следующим:

  • Пузырящегося: Событие сначала выпустило для целевого события элемента. Затем он запускается для родителя, потом родителя его родительского элемента и так далее до корневого элемента (часто это окно).
  • Туннелирование: Событие сначала запускается для элемента корневого пользовательского интерфейса, а затем вниз по дереву элементов пользовательского интерфейса , вдоль маршрута к целевому элементу.
  • Direct: Событие запускается только для элемента цели.

enter image description here

Как это связано с Handled собственности? Когда событие использует технологию барботирования или туннелирования маршрутизации, свойство Handled используется для прекращения распространения события вниз или вверх по дереву элементов пользовательского интерфейса.

Теперь почему не KeyDown прекращение события, распространяющегося, если вы отметили его как Handled? Потому что событие KeyDown использует пузырьковую стратегию. Это означает, что текстовое поле уже обрабатывает событие KeyDown, прежде чем оно будет обработано в Window обработчике, где вы устанавливаете Handled в true.

По этой причине вы должны использовать PreviewKeyDown, который использует стратегию туннелирования. Ваш обработчик окна проверяет событие, помечает его как Handled, если необходимо. Если он отмечен как Handled, он не будет запущен вниз по дереву пользовательского интерфейса для целевой цели.

Вы можете просмотреть это как соглашение в .NET framework. PreviewX - это события, которые используют стратегию туннелирования и являются аналогами X событий, которые используют стратегию bubbling.

To learn more about Routed Events visit this MSDN page. Вы найдете MSDN - хороший источник информации о WPF.

+0

Я добавил, что код это. Без изменений. Все еще делает то, что он делал раньше. – Emrys90

+0

Попробуйте обновленный пример. –

+0

У меня есть KeyDown, обработанный прямо сейчас через свойство события окна WPF. Какая польза от него будет запрограммирована? – Emrys90

1

Попробуйте это:

private void Window_KeyDown(object sender, KeyEventArgs e) 
    { 
     switch (e.Key) 
     { 
      case Key.NumPad1: 
      case Key.D1: 
       addInput('1'); 
       MyTextBox.Focus(); // <-- NEW LINE OF CODE 
       break; 
      case Key.Return: 
       MessageBox.Show("Enter!"); 
       MyTextBox.Focus(); // <-- NEW LINE OF CODE 
       break; 
     } 
    } 
+0

В обработчике кнопок я добавил this.Focus(), чтобы попытаться сфокусировать MainWindow. Без изменений. – Emrys90

+0

@ Emrys90: Почему вы пытаетесь установить фокус на окно, а не на текстовое поле ввода? Вы можете обрабатывать нажатие клавиши в текстовом поле? –

+0

Текстовое поле доступно только для чтения. Я обрабатываю ввод с помощью кнопок или нажатия клавиш для добавления символа, если это допустимый ввод. – Emrys90

0

установить Focusable ложь:

<Button Focusable="False" Click="Button_Click" />