I would like to adjust the behavior of a TextBox
, so that SHIFT + ENTER on the keyboard inserts a new line, while just ENTER executes a different command (such as changing focus or pressing "send" like in messaging apps).
By default, the AcceptsReturn
property of the TextBox
being set to true
inserts a new line when ENTER is pressed. Changing AcceptsReturn
to false
seems to prevent the new line from working at all, even if I manually add the new line:
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);
}
}
}
Based on this post, I was able to come up with a workaround that functionally works, but has a visual side effect. I set AcceptsReturn
to true
, and then manually remove the new line when SHIFT is not pressed, followed by executing the code I want when just ENTER is pressed. The side effect is that the textbox expands to accommodate the new line, then immediately shrinks again, suggesting that its automatically handling the ENTER input before my handler is even run. The code for this follows:
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);
}
}
}
Is there a different way to do this, or a way to get rid of that side effect? I tried adjusting the e.IsHandled
value, but that didn't work (which makes sense, if the default behavior is running before my code).
(In continuation from comment)You can use PreviewKeyDown Event as keydown event will not fire for system handled keys
Handling the PreviewKeyDown event, and marking the event as "handled" prevents the new line from being added in the first place (and thus also prevents the side effect). The full working code follows: