WPF:如何防止控件窃取关键手势?

在我的WPF应用程序中,我想将一个输入手势附加到命令,以便输入手势在主窗口中全局可用,无论哪个控件具有焦点。

在我的情况下,我想将Key.PageDown绑定到命令,但是,只要某些控件接收焦点(例如TextBox或TreeView控件),这些控件就会接收键事件并且不再触发命令。 这些控件没有定义特定的CommandBindingsInputBindings

这是我定义输入手势的方式:

XAML:

            

码:

 using System; using System.Windows; using System.Windows.Input; public static class Commands { private static RoutedUICommand _myCommand; static Commands() { _myCommand = new RoutedUICommand("My Command", "My Command", typeof(Commands), new InputGestureCollection() { new KeyGesture(Key.PageDown, ModifierKeys.None) }); } public static ICommand MyCommand { get { return _myCommand; } } } public partial class Window1 : Window { public Window1() { InitializeComponent(); CommandBinding cb = new CommandBinding(); cb.Command = Commands.MyCommand; cb.Executed += new ExecutedRoutedEventHandler(cb_Executed); cb.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute); this.CommandBindings.Add(cb); } void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; } void cb_Executed(object sender, ExecutedRoutedEventArgs e) { this.label1.Content = string.Format("My Command was executed {0}", DateTime.Now); } } 

我已经尝试捕获窗口的PreviewKeyDown事件并将其标记为已处理这没有达到预期的效果。 我还将Focusable属性设置为false 。 这有助于TextBox控件,但不适用于TreeView(并且具有不必要的效果,TextBox不再可以编辑,因此它不适合我)。

所以我的问题是如何定义一个在主窗口中无处不在的键盘快捷键?

以下解决方法似乎具有将命令全局化到窗口所需的效果; 但是,我仍然想知道在WPF中是否有更简单的方法可以做到这一点:

 private void Window_PreviewKeyDown(object sender, KeyEventArgs e) { foreach (InputBinding inputBinding in this.InputBindings) { KeyGesture keyGesture = inputBinding.Gesture as KeyGesture; if (keyGesture != null && keyGesture.Key == e.Key && keyGesture.Modifiers == Keyboard.Modifiers) { if (inputBinding.Command != null) { inputBinding.Command.Execute(0); e.Handled = true; } } } foreach (CommandBinding cb in this.CommandBindings) { RoutedCommand command = cb.Command as RoutedCommand; if (command != null) { foreach (InputGesture inputGesture in command.InputGestures) { KeyGesture keyGesture = inputGesture as KeyGesture; if (keyGesture != null && keyGesture.Key == e.Key && keyGesture.Modifiers == Keyboard.Modifiers) { command.Execute(0, this); e.Handled = true; } } } } } 

}

使用PreviewKeyDown正是你应该做的……从下到上触发“PreviewXYZ”事件(所以Window首先获取它,然后是控件)……这样你就可以做任何你想做的事情了。窗口“级别。

然后,您可以选择说“IsHandled = true”,这会阻止它进入下一个控件(就您而言),但您不必这样做。 如果您希望事件冒泡,那么只需添加您的代码并将“IsHandled”保留为false。

不幸的是,在WPF中,一些控件在内部硬编码了一些键盘处理。 主窗口中的PreviewKeyDown处理程序是答案

如何定义在主窗口中无处不在的键盘快捷键

题。 是的,这确实意味着你可能想要手动选择PreviewKeyDown中的关键事件的开关/案例…