【问题标题】:Capturing Ctrl-X with the KeyDown event of a textbox in WPF使用 WPF 中文本框的 KeyDown 事件捕获 Ctrl-X
【发布时间】:2020-02-21 08:22:41
【问题描述】:

当用户使用 KeyDown 事件按下 ctrl-x 时,我试图触发一个事件。这对 ctrl-D 效果很好,但是当按下 ctrl-x 时事件不会触发。我猜这是因为 ctrl-x 是“剪切”命令。 ctrl-X按下时有什么办法触发事件吗?

private void textBox_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyboardDevice.IsKeyDown(Key.LeftCtrl) || e.KeyboardDevice.IsKeyDown(Key.RightCtrl))
    {
        switch (e.Key)
        {
            case Key.D:
                //handle D key
                break;
            case Key.X:
                //handle X key
                break;
        }
    }
}

【问题讨论】:

  • 为什么不处理命令而不处理事件?
  • 我该怎么做,有没有办法覆盖 TextBox 的“剪切”命令?

标签: c# wpf


【解决方案1】:

要在 wpf 中做到这一点,我试试这个:

private void HandleKeyDownEvent(object sender, KeyEventArgs e)
{
    if (e.Key == Key.X && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
    {
        MessageBox.Show("You press Ctrl+X :)");
    }
}

【讨论】:

  • 你为什么写: if (e.Key == Key.X && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { } 而不是 if (e.Key == Key. X && (Keyboard.Modifiers == ModifierKeys.Control)) { } ?
  • 它不在我的“if”语句中。知道为什么吗?
  • @StepanIvanenko 因为修饰符是标志,如果您有多个标志,则无法匹配。他使用二进制代码仅提取所需的控制标志。
  • @GeorgiG 这不是一个好主意,因为通常键绑定应该只在完全匹配时触发,所以在这种情况下不适合 Ctrl+Alt+X 之类的东西。
  • 我相信你也可以像这样检查控制存在:e.KeyboardDevice.Modifiers.HasFlag(System.Windows.Input.ModifierKeys.Control)
【解决方案2】:

您可以覆盖现有的剪切命令:

<TextBox>
    <TextBox.InputBindings>
        <KeyBinding Key="X" Modifiers="Control" Command="{Binding TestCommand}" />
    </TextBox.InputBindings>
</TextBox>

你需要创建一个command

【讨论】:

  • 谢谢,我无法让它在 xaml 中工作(甚至为命令创建了一个依赖属性),但它在后面的代码中运行良好。
  • 但是命令通常在视图模型级别运行,而复制功能则扩展到代码隐藏和视图模型。事实上,如果您允许对列进行重新排序,则在不违反 MVVM 的情况下,您无法从视图模型中知道列的位置。
  • @AgostinoX 您需要将更多信息绑定到虚拟机,或者如果无法做到这一点,请查看视图中的事件,然后将事件中的信息传递给虚拟机命令或方法。跨度>
  • 另一方面,我发现自己想知道这是否是仅查看代码的情况。比方说,如果复制粘贴操作类似于手工编辑,那么模型为什么要意识到它并将其作为不同的操作来处理?
  • @AgostinoX 当然,这取决于操作应该做什么。
【解决方案3】:

我正在使用这种方法:

private void SomeWindow_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.X && (e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0)
    {
        //Ctrl + X is pressed
    }
}

【讨论】:

    【解决方案4】:

    大多数答案都能完成工作,但会让调试变得很痛苦。由于首先按下 CTRL,因此应该将其分开,以便可以跳过它并仅由单个 if 检查。以下应该是高效且易于调试的。

    public MyApp() {
        // other constructor code
        KeyDown += MyApp_KeyDown;    
    }
    
    private void MyApp_KeyDown(object sender, KeyEventArgs e) {
        // hold that CTRL key down all day... you'll never get in unless there's another key too. 
        if (Keyboard.Modifiers == ModifierKeys.Control && e.Key!=Key.LeftCtrl && e.Key != Key.RightCtrl) 
        {
            switch (e.Key) // <--- Put the BREAK here.  Stops iff there's another key too.
            {
                case Key.C: UndoRedoStack.InsertInUnDoRedoForCopy(CopyArgs); break;
                case Key.X: UndoRedoStack.InsertInUnDoRedoForCut(CutArgs); break;
                case Key.V: UndoRedoStack.InsertInUnDoRedoForPaste(PasteArgs); break;
                case Key.Y: UndoRedoStack.Redo(1); break;
                case Key.Z: UndoRedoStack.Undo(1); break;
                default: break;
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      尝试在 keydown 事件中关注

             if (e.Control == true && e.KeyCode==keys.x)
             {
                  e.Handled = true;
                  textBox1.SelectionLength = 0;
                  //Call your method
             }
      

      【讨论】:

      • 我假设 e 对象是 KeyEventArgs。这似乎没有 Control 或 KeyCode 属性。有关代码,请参见我上面的编辑。该事件将为“ctrl”键触发,但在按住“ctrl”键的同时按下“x”键时不会触发
      • 您在我发布答案后添加了 wpf,这就是为什么有些混乱
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多