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 вручную...

Другие вопросы по тегам