在 UWP 中对多行文本框使用 SHIFT + ENTER

Use SHIFT + ENTER for multiline textbox in UWP

我想调整 TextBox 的行为,以便键盘上的 SHIFT + ENTER 插入一个新行,而只是 ENTER 执行不同的命令(例如更改焦点或按 "send" 就像在消息传递应用程序中一样)。

默认情况下,TextBoxAcceptsReturn 属性 设置为 true 时会在按下 ENTER 时插入一个新行。将 AcceptsReturn 更改为 false 似乎根本无法阻止新行工作,即使我手动添加新行:

private void ContentTextBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
    // NOTE - AcceptsReturn is set to false in XAML.
    if (e.Key == VirtualKey.Enter)
    {
        var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
        if ((keyState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
        {
            // SHIFT is pressed, so add a new line.
            this.ContentTextBox.Text += "\r";
        }
        else
        {
            // SHIFT is not pressed, so execute my ENTER logic.
            this.Focus(FocusState.Programmatic);
        }
    }
}

基于 this post,我想出了一个功能可行但有视觉副作用的解决方法。我将 AcceptsReturn 设置为 true,然后在按下 SHIFT 而不是 时手动删除新行,然后在按下 ENTER 时执行我想要的代码。副作用是文本框扩展以容纳新行,然后立即再次收缩,这表明它在我的处理程序 运行 之前自动处理 ENTER 输入。代码如下:

private void ContentTextBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
    // NOTE - AcceptsReturn is set to true in XAML.
    if (e.Key == VirtualKey.Enter)
    {
        // If SHIFT is pressed, this next IF is skipped over, so the
        //     default behavior of "AcceptsReturn" is used.
        var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
        if ((keyState & CoreVirtualKeyStates.Down) != CoreVirtualKeyStates.Down)
        {
            // SHIFT is not pressed, so remove the new line.
            string textboxText = this.ContentTextBox.Text;
            textboxText = textboxText.Remove(textboxText.Length - 1);
            this.ContentTextBox.Text = textboxText;

            // Execute my ENTER logic.
            this.Focus(FocusState.Programmatic);
        }
    }
}

有没有其他方法可以做到这一点,或者有什么方法可以消除这种副作用?我尝试调整 e.IsHandled 值,但这没有用(这是有道理的,如果默认行为是 运行ning 在我的代码之前)。

处理 PreviewKeyDown 事件,并将该事件标记为 "handled" 可防止首先添加新行(因此也可防止副作用)。完整的工作代码如下:

private void ContentTextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
    // NOTE - AcceptsReturn is set to true in XAML.
    if (e.Key == VirtualKey.Enter)
    {
        // If SHIFT is pressed, this next IF is skipped over, so the
        //     default behavior of "AcceptsReturn" is used.
        var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
        if ((keyState & CoreVirtualKeyStates.Down) != CoreVirtualKeyStates.Down)
        {
            // Mark the event as handled, so the default behavior of 
            //    "AcceptsReturn" is not used.
            e.Handled = true;
        }
    }
}

private void ContentTextBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
    // NOTE - AcceptsReturn is set to true in XAML.
    if (e.Key == VirtualKey.Enter)
    {
        // If SHIFT is pressed, this next IF is skipped over, so the
        //     default behavior of "AcceptsReturn" is used.
        var keyState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
        if ((keyState & CoreVirtualKeyStates.Down) != CoreVirtualKeyStates.Down)
        {
            // SHIFT is not pressed, so execute my ENTER logic.
            this.Focus(FocusState.Programmatic);
        }
    }
}

(接续评论)您可以使用 PreviewKeyDown 事件,因为系统处理的键不会触发 keydown 事件

  private void TextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down)&& e.Key == Windows.System.VirtualKey.Enter)
            {
               //Add New Line
            }
            else if (e.Key == Windows.System.VirtualKey.Enter)
            {
                //This will prevent system from adding new line
                e.Handled = true;
            }
            else
            {
                e.Handled = false;
            }
        }