簡體   English   中英

WPF:如何防止控件竊取關鍵手勢?

[英]WPF: How to prevent a control from stealing a key gesture?

在我的WPF應用程序中,我想將一個輸入手勢附加到命令,以便輸入手勢在主窗口中全局可用,無論哪個控件具有焦點。

在我的情況下,我想將Key.PageDown綁定到命令,但是,只要某些控件接收焦點(例如TextBox或TreeView控件),這些控件就會接收鍵事件並且不再觸發命令。 這些控件沒有定義特定的CommandBindingsInputBindings

這是我定義輸入手勢的方式:

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不再可以編輯,因此它不適合我)。

所以我的問題是如何定義一個在主窗口無處不在的鍵盤快捷鍵?

以下解決方法似乎具有將命令全局化到窗口所需的效果; 但是,我仍然想知道在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中的關鍵事件的開關/案例...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM