WPF TreeView 键绑定 Ctrl + Down

WPF TreeView KeyBinding Ctrl + Down

我正在尝试将树视图中的 Ctrl + Down 作为自定义快捷键处理。我试过以下代码:

<Window x:Class="WpfTreeIssue.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfTreeIssue"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800"
    x:Name="_this">
<Grid DataContext="{Binding ElementName=_this}">
    <TreeView>
        <TreeView.InputBindings>
            <KeyBinding
                Key="Down" Modifiers="Ctrl"
                Command="{Binding ControlDownCommand}" />
            <KeyBinding
                Key="A"
                Command="{Binding ControlDownCommand}" />
        </TreeView.InputBindings>

        <TreeViewItem Header="Level 1" IsExpanded="True">
            <TreeViewItem Header="Level 2.1" />
            <TreeViewItem Header="Level 2.2" IsExpanded="True">
                <TreeViewItem Header="Level 3.1" />
                <TreeViewItem Header="Level 3.2" />
            </TreeViewItem>
            <TreeViewItem Header="Level 2.3" />
        </TreeViewItem>
    </TreeView>
</Grid>

代码隐藏:

public partial class MainWindow : Window
{
    public ICommand ControlDownCommand
    {
        get
        {
            return new RelayCommand<KeyBinding>(x => OnControlDown(x));
        }
    }

    private void OnControlDown(KeyBinding keyBinding)
    {
        Console.Write("HELLO");
    }

    public MainWindow()
    {
        InitializeComponent();
    }
}

RelayCommand 是一个基本的 ReplayCommand,如下所示:https://www.c-sharpcorner.com/UploadFile/20c06b/icommand-and-relaycommand-in-wpf/

我已经为 Ctrl-DownA 添加了 KeyBindings。 A 快捷方式工作正常,但 Ctrl-Down 不起作用。

我已经尝试删除 Ctrl 修饰符,但向下快捷键仍然不起作用(它移动了选定的树项目,这是有道理的)。有趣的是,如果您导航到树视图中的最后一项并按下(在这种情况下 Ctrl-down 不起作用),则向下快捷方式确实有效。

关于如何让 Ctrl-Down KeyBinding 在我的 TreeView 上工作有什么建议吗?

编辑:我也试过重写 TreeView 的 OnKeyDown 和 OnPreviewKeyDown 方法,但没有成功。见下文:

public class CustomTreeView : TreeView
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.Key == Key.Down)
        {
            Console.WriteLine("Down arrow");
            if ((e.KeyboardDevice.IsKeyDown(Key.RightCtrl) || e.KeyboardDevice.IsKeyDown(Key.LeftCtrl)))
            {
                Console.WriteLine("TEST");
                e.Handled = true;
            }
        }

        base.OnKeyDown(e);
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (e.Key == Key.Down)
        {
            Console.WriteLine("Down arrow");
            if ((e.KeyboardDevice.IsKeyDown(Key.RightCtrl) || e.KeyboardDevice.IsKeyDown(Key.LeftCtrl)))
            {
                Console.WriteLine("TEST");
                e.Handled = true;
            }
        }

        base.OnPreviewKeyDown(e);
    }
}

如果我按住 Ctrl 键并按下行 Console.WriteLine("Down arrow"); 永远不会被击中(不会发送向下箭头事件)。如果我只是按下,行会被击中,但 ctrl 修饰符未设置。

TreeView 控件中有一段代码可以处理 Ctrl+Down,因此您的绑定无法正常工作,因为按键事件已经处理完毕。您需要覆盖 TreeView 上的 OnKeyDown 才能执行您自己的操作。

更新: 这是一个测试样本

protected override void OnKeyDown(KeyEventArgs e)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                if (System.Windows.Input.Key.Down == e.Key)
                {
                    System.Diagnostics.Trace.WriteLine("Ctlr+Down");
                    e.Handled = true;
                }
            }

            if (!e.Handled)
            {
                base.OnKeyDown(e);
            }
        }