代码之家  ›  专栏  ›  技术社区  ›  Dirk Vollmar

WPF:如何防止控件窃取关键手势?

  •  14
  • Dirk Vollmar  · 技术社区  · 16 年前

    在我的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 回复  |  直到 16 年前
        1
  •  10
  •   Dirk Vollmar    16 年前

    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
  •  4
  •   Timothy Khouri    16 年前

    预览向下 这正是你想要的 应该 做“PreviewXYZ”事件是自下而上触发的(因此窗口首先获取它,然后是控件)。。。这让你可以在“窗口”级别上做任何你想做的事情。

    然后,您可以选择说“IsHandled=true”,这将阻止它进入下一个控件(就您而言),但您不必这样做。如果希望事件冒泡,那么只需添加代码并将“IsHandled”保留为false。

        3
  •  2
  •   Anvaka    16 年前

    不幸的是,在WPF中,一些控件内部硬编码了一些键盘处理。这个 PreviewKeyDown 主窗口中的处理程序是

    问题。是的,这确实意味着您可能需要在PreviewKeyDown中手动选择关键事件的开关/大小写。。。