2013-03-19 216 views
1

我正在用C#编程计算器,我正在尝试向它添加键盘输入。问题在于,如果我在GUI上单击一个按钮,那么Enter/Return键会将焦点放在那个上面。当按下返回键时,它再次单击该键,而不是由我的KeyDown事件处理程序处理。我怎样才能解决这个问题?键盘输入返回键

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 2013-03-19 16:22:22

+0

添加一个事件处理程序代码。 – Emrys90 2013-03-19 16:23:27

+2

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 – 2013-03-19 16:26:05

回答

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

为什么你需要设置Handledtrue? WPF中的事件在几个UI元素上触发,其方式取决于它的“路由策略”。当您的事件处理程序将Handled设置为true时,该事件的可见性将仅限于其他UI元素。很快,它不会在其他UI元素中触发。要详细了解上述解决方案的详细信息,请阅读以下答案的其余部分。


如果您想正确使用WPF中的事件,您需要了解一些事项。事件附加到UI元素(文本框,按钮等),事件处理程序可以连接到这些UI元素。而且,UI元素以树结构进行组织。每个元素都有其父元素,直到根UI元素。如前所述,根据“路由策略”在多个元素上触发事件。这里的多个元素意味着一个事件所针对的元素,它是父母,直到根元素为止。事件路由策略可以如下:

  • 冒泡:事件首先被解雇事件的目标元素。然后,它的父项,然后是父项的父项,直到根元素为止(通常是Window)
  • 隧道:首先针对根UI元素触发事件,然后关闭UI元素树,沿着目标元素的路线。
  • 直接:仅针对目标元素触发事件。

enter image description here

这是如何与Handled财产?当事件使用冒泡或隧道路由策略时,Handled属性用于停止向下或向上UI元素树的传播。

现在,为什么KeyDown事件在您将其标记为Handled时停止传播?因为KeyDown事件使用冒泡策略。这意味着一个文本框在处理KeyDown事件之前已经到达窗口处理程序,您可以在其中设置Handledtrue

因此,您应该使用使用隧道策略的PreviewKeyDown。您的窗口处理程序检查事件,如果需要将其标记为Handled。如果它被标记为Handled它不会被触发到UI树到事件目标。

您可以将其视为.NET框架中的约定。 PreviewX是使用隧道策略的事件,并且与使用bubbling策略的X事件相对应。

To learn more about Routed Events visit this MSDN page.你会发现MSDN是关于WPF的一个很好的信息来源。

+0

我添加了它的代码。不用找了。仍然做它以前做的。 – Emrys90 2013-03-19 16:27:35

+0

尝试更新示例。 – 2013-03-19 16:49:26

+0

我现在通过WPF窗口的事件属性来处理KeyDown。以编程方式获得什么好处? – Emrys90 2013-03-19 17:20:18

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 2013-03-19 16:29:09

+0

@ Emrys90:为什么试图将焦点设置到窗口而不是输入的文本框?你可以在文本框中处理按键吗? – 2013-03-19 17:11:46

+0

文本框是只读的。如果输入是有效的,我使用按钮或按键来处理输入以追加字符。 – Emrys90 2013-03-19 17:17:45

0

设置可聚焦为false:

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