如何阻止 WPF KeyDown 事件从某些包含的控件(例如 TextBox)冒泡?

Posted

技术标签:

【中文标题】如何阻止 WPF KeyDown 事件从某些包含的控件(例如 TextBox)冒泡?【英文标题】:How do I stop WPF KeyDown events from bubbling up from certain contained controls (such as TextBox)? 【发布时间】:2014-09-12 10:06:42 【问题描述】:

我的程序很大,并且使用 WPF,我想要一个使用“R”的全局快捷键,没有修饰符。 有许多控件,例如 TextBox、ListBox、ComboBox 等,它们都在控件本身内部使用字母,这很好 - 这对我来说是正确的。 但是 - 我想让 KeyDown 事件不会冒泡到主窗口,例如,只要用户在 TextBox 中键入字母“R”,它就会触发快捷方式。 理想情况下,我希望能够做到这一点,而不必指定(并执行 if-then 逻辑)每个可能接收正常字母按键的控件实例/类型(不仅仅是 TextBox 控件,尽管它们是最严重的违规者)。

【问题讨论】:

【参考方案1】:

只需检查 Window 上的 KeyDown 事件处理程序中的 OriginalSource 是什么:

private void Window_KeyDown(object sender, KeyEventArgs e) 
    if(e.OriginalSource is TextBox || e.OriginalSource is DateTimePicker) //etc
    
        e.Handled = true;
        return;
    

或者,如果您正在使用 InputBindings,请尝试在您的 Window 上的 KeyDownPreviewKeyDown 事件中设置 e.Handled = true,而不是单独的控件。无论如何,我认为OriginalSource 是您答案的关键。 (我发誓这不是双关语)。

【讨论】:

e.Handled 设置为true 绝对是正确的方法。第一个提议的解决方案实际上并不能防止冒泡。 @MathiasLykkegaardLorenzen 我很感兴趣,它是如何防止冒泡的? 通过“第一个提出的解决方案”我指的是他自己的代码,当e.OriginalSourceWindow 时,它基本上只是应用逻辑。我指的不是你的代码,@lll。事实上,我对你的代码投了赞成票。 这不是一个坏主意——但是,它忽略了在窗口不是主要焦点时可能按下的任何快捷键,这是很常见的情况。 @redroze:对不起,当窗口不是主要焦点时,我不明白你的意思?我不希望您指的是其他窗口。但是如果 KeyDown 事件发生在 Window 中的某个地方,它会冒泡到处理程序,除非被处理,对吧?【参考方案2】:

当您处理KeyDown 事件时有一个事件,它应该传递给您一个KeyEventArgs。从那里您可以将Handled 设置为true,这样它就不会冒泡。

样本

private void TextBoxEx_KeyAction(object sender, KeyEventArgs e)

  e.Handled = true;

【讨论】:

这也会阻止 TextBox 实际输入文本,因为它会阻止 TextBox 处理文本合成事件。 嗯,不,除非您覆盖一个事件并且不调用 base.OnKeyPressed(e);那是OnKeyPressed 那么是的,它不会处理输入文本。 @Ill:那我一定是误解了你在做什么。创建一个带有TextBox 的空项目,并添加一个KeyDown 事件处理程序,只包含e.Handled = true。它不会接受任何文本。 Troels 是正确的,可以防止输入任何文本。 另外,我必须为每个可能接受文本输入的控件(当前和未来)添加一个事件处理程序。

以上是关于如何阻止 WPF KeyDown 事件从某些包含的控件(例如 TextBox)冒泡?的主要内容,如果未能解决你的问题,请参考以下文章

wpf中 closing事件和unload事件有啥区别?

input 事件监听的顺序

WPF学习笔记-如何按ESC关闭窗口

keydown,keypress,keyup三者之间的区别

vb中keydown事件中只有一句keycode=0,却不能阻止键盘输入。是vb坏了还是我方式错了

WPF学习第十六章 键盘输入