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

3 回答 3

2

您需要处理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 元素上触发的,其方式取决于它的“路由策略”。当您的事件处理程序设置Handledtrue时,该事件的可见性将仅限于其他 UI 元素。很快,它不会在其他 UI 元素中触发。要了解有关上述解决方案的详细信息,请阅读下面的其余答案。


如果要在 WPF 中正确使用事件,则需要了解一些事项。事件附加到 UI 元素(文本框、按钮等),并且事件处理程序可以连接到这些 UI 元素。此外,UI 元素以树状结构组织。每个元素都有它的父元素,直到根 UI 元素。如前所述,事件在多个元素上触发,具体取决于它们的“路由策略”。这里的多个元素是指事件所针对的元素及其父元素,直到根元素。事件路由策略可以如下:

  • 冒泡:首先为事件目标元素触发事件。然后,它被触发它的父元素,然后是它的父元素的父元素,依此类推,直到根元素(通常是窗口)
  • Tunneling:首先为根 UI 元素触发事件,然后沿着 UI 元素树向下,沿着到达目标元素的路线。
  • Direct:仅针对目标元素触发事件。

在此处输入图像描述

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

现在,当您将其标记为 时,为什么KeyDown事件没有停止传播Handled?因为KeyDown事件使用冒泡策略。这意味着文本框在到达您设置Handledtrue.

出于这个原因,您应该使用PreviewKeyDownwhich uses tunneling 策略。您的窗口处理程序检查事件,将其标记为Handled需要。如果它被标记为Handled它不会被触发向下 UI 树到事件目标。

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

要了解有关路由事件的更多信息,请访问此 MSDN 页面。您会发现 MSDN 是关于 WPF 的一个很好的信息来源。

于 2013-03-19T16:24:48.527 回答
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;
        }
    }
于 2013-03-19T16:24:20.377 回答
0

将 Focusable 设置为 false:

<Button Focusable="False" Click="Button_Click" />
于 2013-03-19T18:11:48.607 回答