【问题标题】:Weird KeyUp behaviour (main form handles events from child?!)奇怪的 KeyUp 行为(主窗体处理来自孩子的事件?!)
【发布时间】:2012-04-17 17:37:55
【问题描述】:

问题:

  1. KeyUp 由主窗口中的网格处理 (Grid_KeyUp)
  2. 主窗口显示一个子窗口(例如MessageBox.Show(...)
  3. 用户按下 [Return] (Keys.Return) 关闭MessageBox
  4. 主窗口实际上从 MessageBox 中的该按键获取 KeyUp 事件

我有一个非常简单的孤立样本,它显示了我遇到的问题。只需创建一个空的 WPF 项目并使用此 XAML:

<Grid KeyUp="Grid_KeyUp">
    <Button Click="Button_Click"></Button>
</Grid>

还有代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Grid_KeyUp(object sender, KeyEventArgs e)
    {
        Console.WriteLine("KEYUP: " + e.Key);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(this, "TEST");
    }
}

如果单击按钮并按 [Return] 关闭 MessageBox,输出窗口将打印:

KEYUP: Return

奇怪的事实:

  1. 我在按 [Escape] 时得到相同的行为(KEYUP: Escape 被打印),但是当我按 [Space] 时,控制台没有打印任何内容!
  2. e.Source 和 e.OriginalSource 指向主窗口中的按钮(这显然是错误的)。
  3. 如果您在 MessageBox.Show(...) 之后放置断点,则事件不会由 out KeyUp 处理程序处理(即输出为空)。

谁能向我解释发生了什么?

PS 目标框架是:.NET 4 客户端

【问题讨论】:

    标签: wpf keyup routedevent


    【解决方案1】:

    很明显,当您按下 Enter 或 Escape 时,消息框会关闭,在您抬起按钮之前,MainWindow 获得焦点并同时捕捉到 KeyPress

    空格键没有发生这种情况的原因是按下空格键会按下按钮,但直到您自己释放空格键后才会释放它。这意味着空格键在按钮“未按下”之前被释放,因此MessageBox 仅在空格键被释放后关闭,因此MainWindow 不会捕捉按钮按下。

    您可以按住空格键进行测试。 您将看到该按钮被按住,但直到您释放它才被按下。

    您可以创建一个在MessageBox 关闭后熄灭的标志。检查它是否是第一个 KeyPress(并可能检查它是否在关闭后不到 10 毫秒发生)然后忽略它。

    我知道,它很丑,但我认为你无能为力(如果我是对的)

    【讨论】:

    • 这实际上是一个很好的解释 :) 由于某种原因,我自己无法做到这一点。 (顺便说一句,它与 WinForms/WPF 没有任何关系,因为纯 WPF 应用程序的行为完全相同)。谢谢!
    • @Jefim 测试过,你是对的。考虑到当您在窗口中获得多个弹出窗口时,通常只需按住 Enter 键即可摆脱所有这些,这种行为实际上是有意义的。我想我应该在提出这样的事情之前考虑过(并测试过)
    • 嗯,你的总体想法还是很正确的,所以没有伤害:) 是的,现在这确实有意义。
    • 我遇到了同样的问题,为我解决的方法是捕获 PreviewKeyDown 而不是 KeyUp。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多