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 больше нельзя редактировать, поэтому это не решение для меня).
Итак, мой вопрос, как я могу определить сочетание клавиш, которое работает везде в главном окне?
3 ответа
Следующий обходной путь, похоже, дает желаемый эффект наличия глобальной команды для окна; Тем не менее, я все еще задаюсь вопросом, нет ли более простого способа сделать это в 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" запускаются снизу вверх (поэтому сначала окно получает его, а затем элемент управления)... что позволяет вам делать все, что вы хотите сделать глобально на " Окно "Уровень.
Затем вы можете выбрать "IsHandled = true", что помешает ему перейти к следующему элементу управления (насколько вам это интересно), но вам не нужно этого делать. Если вы хотите, чтобы событие всплыло, просто добавьте свой код и оставьте "IsHandled" равным false.
К сожалению, в WPF некоторые элементы управления имеют некоторую встроенную обработку клавиатуры. PreviewKeyDown
Обработчик в главном окне является ответом на
Как определить сочетание клавиш, которое работает везде в главном окне
вопрос. И да, это означает, что вы можете выбрать переключатель / регистр для ключевых событий в PreviewKeyDown вручную...