c# - WPF 如何管理 ENTER 命中 TextBox 以进行消息传递

标签 c# wpf textbox keydown

以一个简单的消息程序为例,例如 Steam 好友对话。

当您点击 ENTER 时,消息被发送,并且消息字段被清空

当您输入 CTRL/SHIFT + ENTER 时,会创建一个换行符。如果您的光标不在输入文本的末尾,然后出现在您光标之后的所有文本将被发送到换行符

那么,您是如何完成这样的壮举的?

此外,我想知道如何拥有上述功能以及如何仍然能够将多行文本粘贴到消息字段中。

现在,这是我的代码。这是一些事情,但并没有完成所有的工作:

private bool ctrlOrShift = false;
private void MessageField_KeyDown( object sender, KeyEventArgs e )
{
    if( e.Key == Key.LeftCtrl || e.Key == Key.LeftShift )
    {
        ctrlOrShift = true;
    }

    else if( e.Key == Key.Enter && ctrlOrShift != true && !MessageField.AcceptsReturn )
    {  
         AsyncSendMessage();
    }
    else if( e.Key == Key.Enter && ctrlOrShift != true && MessageField.AcceptsReturn )
    {
         MessageField.AcceptsReturn = false;
    }
    else if( e.Key == Key.Enter && ctrlOrShift == true )
    {
         ctrlOrShift = false;
         MessageField.AcceptsReturn = true;
         MessageField.Text += System.Environment.NewLine;
         MessageField.Select( MessageField.Text.Length, 0 );
         MessageField.AcceptsReturn = false;
    }
    else
    {
         ctrlOrShift = false; // Canceled because follow-up key wat not ENTER !
    }
}

出现以下情况:

  1. 使用 CTRSHIFT,我可以在我的 TextBox 中创建一个新行 :) ;
  2. 我无法从剪贴板粘贴多行文本:只会粘贴第一行,没有其他内容:( ;
  3. 如果我使用 CTRL + V 粘贴内容,MessageField_KeyDown 事件会考虑 CTRL 命中,因此,如果我按 ENTER,不会发送消息,而是创建换行符:/(在您粘贴内容并立即发送的情况下);
  4. 如果我的光标位置在输入文本结束之前,CTR/SHIT + ENTER 将在文本末尾创建一个换行符,而不管光标位置如何:/

那么,我该如何调整这段代码呢?感谢您的帮助!

最佳答案

解决方案的结果是这样的:

正常
Normal

在一个SHIFT + ENTER
之后 enter image description here

当您按下 ENTER 时,它看起来像在 Normal 中,只有框中没有文本

如评论中所述,您可以为多行文本框(如在 Steam 中)使用 AcceptsReturnTextWrapping 属性。 使用 Height = Auto 以获得更好的外观(否则你只有一行,所有其他行都消失了)
XAML
对于文本框:

<TextBox HorizontalAlignment="Left" Height="Auto" Margin="10,10,0,0" 
     TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" 
     Width="497" AcceptsReturn="True" 
     KeyDown="TextBoxKeyDown" PreviewKeyDown="TextBoxPreviewKeyDown"/>

事件处理器:
这并不像我最初想的那么容易 :'D 但我想通了。
当您使用 AcceptsReturn 属性时,Enter KeyAcceptsReturn 处理。所以如果你按下回车,你会看到一个新行而不是一个 Send() 如果你编程是这样的:

private void TextBoxKeyDown(object sender, KeyEventArgs e)
{
    var textbox = sender as TextBox;
    // This will never happen because the Enter Key is handeled before
    // That means TextBoxKeyDown is not triggered for the Enter key
    if (e.Key == Key.Enter &&
        !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) &&
        !(Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift)))
    {
        // Send(textBox.Text)
        textbox.Text = "";
    }
}

因此您需要实现PreviewKeyDown 事件处理程序。因为在 PreviewKeyDown 事件处理程序中,事件通过(父)元素进行路由。 Look at this Answer

另请注意 e.Handled = true 行。否则,Enter 将通过该方法路由到 AcceptsReturn,您将在输入后有 2 行,但文本框为空。 有了这个方法,KeyDown 方法就不再需要了!

private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
    // Enter key is routed and the PreviewKeyDown is also fired with the 
    // Enter key
    var textbox = sender as TextBox;
    // You don't want to clear the box when CTRL and/or SHIFT is down
    if (e.Key == Key.Enter && 
        !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) &&
        !(Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
    {
        textbox.Text = "";
        e.Handled = true;
    }
}

多行文本框的优点是您可以复制和粘贴 + 您对是否按下 CTRL 没有任何问题。

你怎么看?

希望对你有帮助

关于c# - WPF 如何管理 ENTER 命中 TextBox 以进行消息传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30731856/

相关文章:

c# - 更改背景切换按钮

.net - 从 Entity Framework 绑定(bind)数据源时,WPF 设计器不会加载

c# - 如何使用 Quartz 调度程序维护作业历史记录

c# - 从 C# 运行 Python 函数

c# - 使用存储过程的 Entity Framework 并发问题

c# - 内存不足异常的 EPPlus 大型数据集问题

wpf - 卡特尔延迟加载包含 View / View 模型的装配体

wpf - 如何在文本框中添加超链接和文本

mysql - 刷新文本框

c# - 在文本框中多次打印字符串 C#