WPF: Как предотвратить кражу жеста с помощью элемента управления? - PullRequest
14 голосов
/ 14 декабря 2009

В моем приложении 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 ]

10 голосов
/ 14 декабря 2009

Следующий обходной путь, похоже, дает желаемый эффект наличия команды, глобальной для окна; Тем не менее, я все еще задаюсь вопросом, нет ли более простого способа сделать это в 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;
                }
            }
        }
    }
}

}

4 голосов
/ 14 декабря 2009

Использование PreviewKeyDown - это именно то, что вы должны сделать ... события "PreviewXYZ" запускаются снизу вверх (поэтому сначала окно получает их, а затем элемент управления). ... это позволяет вам делать все, что вы хотите сделать глобально на уровне "Window".

Затем вы можете выбрать «IsHandled = true», что помешает ему перейти к следующему элементу управления (насколько вам это интересно), но вам не нужно этого делать. Если вы хотите, чтобы событие всплыло, просто добавьте свой код и оставьте «IsHandled» равным false.

2 голосов
/ 14 декабря 2009

К сожалению, в WPF некоторые элементы управления имеют некоторую встроенную обработку клавиатуры. Обработчик PreviewKeyDown в главном окне является ответом на

Как определить сочетание клавиш, которое работает везде в главном окне

вопрос. И да, это означает, что вы можете выбрать переключатель / регистр для ключевых событий в PreviewKeyDown вручную ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...