I have several Textboxes in a UWP project. If I press the down key inside a textbox, the cursor will jump to the end of the text; unless the cursor is at the very front. If the cursor is at the front of the text, pressing down does nothing. Is there a way to make the cursor jump to the end of the text upon a down key press even if the cursor is at the very front?
I made a new UWP project to test this and the above functionality is the default.
You can use SelectionStart and SelectionLength property in PreviewKeyDown Event
Note: e.Handled has to be set false
/*Xaml Code*/
<TextBox x:Name="SelectionTextBox" PreviewKeyDown="SelectionTextBox_PreviewKeyDown"/>
//C# code
private void SelectionTextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Down)
{
SelectionTextBox.SelectionStart = SelectionTextBox.Text.Length - 1;
SelectionTextBox.SelectionLength = 0;
}
else
{
e.Handled = false;
}
}
Related
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
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;
}
}
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:
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);
}
}
}
I use this code on Enter keypress to move focus to next like the Tab does in a datagrid.
uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
At the end of any row while hitting enter moves the focus to the next line but the selection stays where it was. On the other hand using Tab brings the selection with the focus.
Is there a way to move the selection aswell with some adjustments?
Matt Hamilton's answer is great but not doing the selection.
What you could do, instead of trying to programmatically switch focus, is simulating a tab key press each time the enter key is pressed inside the DataGrid. It would then look something like this:
private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var dataGrid = (DataGrid)sender;
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(dataGrid), 0, Key.Tab)
{
RoutedEvent = Keyboard.KeyDownEvent,
};
dataGrid.RaiseEvent(keyEventArgs);
e.Handled = true;
}
}
I have a WPF Application hostet in a WinForms ElementHost.
When a diacritic character (e.g. "^" or "`") is entered in a Textbox, NOT followed by a literal, changing focus by pressing TAB does not work. A literal character must be typed first to make TAB work again.
In a native WPF application the diacritic gets displayed in the TextBox when pressing TAB, further presses of TAB change focus. The ElementHost seems to inhibit this behavior.
Any Ideas?
A Workaround has been found by overriding OnKeyDown Method and checking e.DeadCharProcessedKey.
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (e.DeadCharProcessedKey == Key.Tab)
{
_ChangeFocus(e);
e.Handled = true;
}
else
{
base.OnPreviewKeyDown(e);
}
}
private static void _ChangeFocus(KeyEventArgs e)
{
var direction = Keyboard.Modifiers == ModifierKeys.Shift ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
var focusedElement = Keyboard.FocusedElement as UIElement;
if (focusedElement != null && focusedElement .MoveFocus(new TraversalRequest(direction)))
e.Handled = true;
}
I have this procedure wich moves the cursor to the next textbox up/down within non multiline textbox.
When using key down from multiline textbox, cursor moves to the next textbox but does not focus in the next textbox when pressing key up idem. With key enter it moves from multiline to the next textbox and focuses it.
What can be the reason ?
I have 8 textboxes which are groupped with tag properties from 0 to 7. TxtboxNbrLimit is set to 8
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Down)
{
if (KeyIndex < TxtboxNbrLimit)
++KeyIndex;
if (KeyIndex == TxtboxNbrLimit)
{
SaveBtn.Select();
return;
}
if (_textBox[KeyIndex].Text != "")
ChangeDone = true;
_textBox[KeyIndex].SelectionStart = 0;
_textBox[KeyIndex].SelectionLength = _textBox[KeyIndex].Text.Length;
_textBox[KeyIndex].Select();
_textBox[KeyIndex].Focus();
}
else
{
if (e.KeyCode == Keys.Up)
{
if (KeyIndex > 0)
--KeyIndex;
_textBox[KeyIndex].SelectionStart = 0;
_textBox[KeyIndex].SelectionLength = _textBox[KeyIndex].Text.Length;
_textBox[KeyIndex].Select();
_textBox[KeyIndex].Focus();
}
}
}
Try to move your logic to key up event instead of key down. That will work fine, TESTED.
Maybe multiline TextBox has some kind of event handler internally to handle up/down keyboard key pressed event, to move cursor between text lines. So your code work will be overridden by that internal behavior.
And in case you put it in key up event, the opposite happened. Your code logic will override effect of TextBox's internal behavior. So if the TextBox contains multiline text, the cursor will move to next/previous TextBox instead of moving between text lines inside the multiline TextBox.
I have a RichTextBox that i am searching text in and I want to be able to control what the enter key does when text is selected. I am able to use this if test below to call the method that I want, but my issue is after the method gets hit when the enter key is pressed it then moves the text to the second line and I want to be able to stop this from happening when the text is highlighted.
I test to check if the text is selected when enter is pressed.
if (IsTextSelected == true)
{
btnSearch_Click(sender, null);
}
You can listen to the PreviewKeyDown event like:
<RichTextBox PreviewKeyDown="RichTextBox_PreviewKeyDown"/>
and in the handler:
private void RichTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
// DO YOUR WORK HERE and then set e.Handled to true on condition if you want to stop going to next line//
e.Handled = true;
}
}