WPF: Как предотвратить контроль от кражи ключевого жеста?
В моем приложении WPF я хотел бы добавить жест ввода к команде, чтобы входной жест глобально был доступен в главном окне, независимо от того, какой элемент управления имеет фокус.
В моем случае я хотел бы привязать Key.PageDown
к команде, однако, как только некоторые элементы управления получат фокус (например, элемент управления TextBox или TreeView), эти элементы управления получают события ключа, и команда больше не запускается, Эти элементы управления не имеют определенных CommandBindings
или InputBindings
.
Вот как я определяю свой входной жест:
XAML:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" >
<StackPanel>
<TreeView>
<TreeViewItem Header="1">
<TreeViewItem Header="1.1"></TreeViewItem>
<TreeViewItem Header="1.2"></TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="2" ></TreeViewItem>
</TreeView>
<TextBox />
<Label Name="label1" />
</StackPanel>
</Window>
код:
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 больше не редактируется, поэтому это не решение для меня).
Итак, мой вопрос: как определить ярлык на клавиатуре, который работает повсюду в главном окне?
Ответы
Ответ 1
Следующий обходной путь, похоже, имеет желаемый эффект от наличия глобальной команды в окне; однако мне все еще интересно, нет ли в 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;
}
}
}
}
}
}
Ответ 2
Использование PreviewKeyDown - это именно то, что вам следует делать... события "PreviewXYZ" запускаются снизу вверх (поэтому окно получает его сначала, затем элемент управления)..., который позволяет вам сделайте все, что вы хотите сделать глобально на уровне "Окно".
Затем вы можете сказать "IsHandled = true", что помешает ему перейти к следующему элементу управления (насколько это касается вас), но вам не нужно это делать. Если вы хотите, чтобы событие пузырилось, просто добавьте свой код и оставьте "IsHandled" равным false.
Ответ 3
К сожалению, в WPF некоторые элементы управления имеют встроенную внутреннюю обработку клавиатуры. Обработчик PreviewKeyDown
в главном окне - это ответ на
Как определить комбинацию клавиш, которая работает повсюду в главном окне
вопрос. И да, это означает, что вы можете захотеть вручную выбрать переключатель/случай для ключевых событий в PreviewKeyDown...