I want to move to the next control when I press the Enter key instead of the Tab key in a WPF MVVM application. How can I achieve this?
7 Answers
Below is an attached property that I've used for just this.
First, example usage:
<TextBox Width="100"
Text="{Binding Name, Mode=TwoWay}"
UI:FocusAdvancement.AdvancesByEnterKey="True" />
(UI is the namespace alias for where I've defined the following.)
The attached property:
public static class FocusAdvancement
{
public static bool GetAdvancesByEnterKey(DependencyObject obj)
{
return (bool)obj.GetValue(AdvancesByEnterKeyProperty);
}
public static void SetAdvancesByEnterKey(DependencyObject obj, bool value)
{
obj.SetValue(AdvancesByEnterKeyProperty, value);
}
public static readonly DependencyProperty AdvancesByEnterKeyProperty =
DependencyProperty.RegisterAttached("AdvancesByEnterKey", typeof(bool), typeof(FocusAdvancement),
new UIPropertyMetadata(OnAdvancesByEnterKeyPropertyChanged));
static void OnAdvancesByEnterKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as UIElement;
if(element == null) return;
if ((bool)e.NewValue) element.KeyDown += Keydown;
else element.KeyDown -= Keydown;
}
static void Keydown(object sender, KeyEventArgs e)
{
if(!e.Key.Equals(Key.Enter)) return;
var element = sender as UIElement;
if(element != null) element.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
You also said "instead of tab," so I'm wondering if you want to suppress the ability to use tab in the usual way. I'd advise against it, as it is a common, well known paradigm, but if that is the case, you can add a PreviewKeyDown
handler in the attached property, check for the tab key, and set Handled = true
for the event args.

- 56,361
- 10
- 99
- 123
-
+1. I needed this to 'be consistent' with the rest of the app which was grid-based.. Press Enter to exit edit mode and move to next field. – Gishu Oct 01 '12 at 09:59
-
@Jay I need a help this code is not working if I need Up key event to work instead of enter key.Can you please suggest – Anindya Oct 16 '13 at 12:19
-
1@AnindyaChatterjee If you want the same behaviour, but with Up key, change `Key.Enter` to `Key.Up`. Anything else, I suggest you post a new question. – Jay Oct 16 '13 at 13:06
-
@Jay For DatePicker control KeyDown Event is not working. I replace KeyDown with PreviewKeyDown than that's works fine. Didn't get what is issue. – Uday Oct 24 '18 at 09:02
If you only want it to work for a few text boxes, Jay's answer is best.
If you want your whole application to work that way, makwana.a's answer is better but can be improved.
Below is my modification of makwana.a's answer, which I have used in numerous applications. It also includes support for moving to the next control via enter if the active control is a check box. Instead of using the tag property to decide whether or not the focus should move, I used the AcceptsReturn
property of the text box. I did this because it defaults to false and will only be set to true on multi-line text boxes. In that case, you won't want the focus to move to the next control on enter anyway.
Declare these event handlers in the OnStartup void of App.xaml
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));
EventManager.RegisterClassHandler(typeof(CheckBox), CheckBox.KeyDownEvent, new KeyEventHandler(CheckBox_KeyDown));
Here are the rest of the methods needed to make it work application wide.
void TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter & (sender as TextBox).AcceptsReturn == false) MoveToNextUIElement(e);
}
void CheckBox_KeyDown(object sender, KeyEventArgs e)
{
MoveToNextUIElement(e);
//Sucessfully moved on and marked key as handled.
//Toggle check box since the key was handled and
//the checkbox will never receive it.
if (e.Handled == true)
{
CheckBox cb = (CheckBox)sender;
cb.IsChecked = !cb.IsChecked;
}
}
void MoveToNextUIElement(KeyEventArgs e)
{
// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;
// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
// Change keyboard focus.
if (elementWithFocus != null)
{
if (elementWithFocus.MoveFocus(request)) e.Handled = true;
}
}
Edit
I updated the code to mark the keystroke as handled if the movement was successful and also toggle the checkbox since the key was handled and will no longer reach it.

- 1,391
- 15
- 41
-
This works really well except I wanted to use it for ComboBoxes as well. But when a ComboBox has IsTextSearchEnabled set to true (it might be IsEditable) the above code traversed twice instead of only once. This is because the above code never "handles" the key event. The body of all key_down events should set the e.Handled to true after calling the MoveToNextUIElement(); – Zamotic Oct 10 '12 at 21:02
-
@Zamotic Good catch. I updated the example to mark the keystroke as handled but only if the focus move was successful. – StillLearnin Oct 12 '12 at 15:31
-
4The answer by Jay is spot on for working in your whole application. Just set the attached property in your TextBox Control Template and they all work as desired. – mcalex Mar 14 '13 at 03:31
-
1@mcalex except that then you have to have a TextBox Control Template and you have to apply that template to every text box. That's a lot of overhead if you don't need it all. – StillLearnin Mar 26 '13 at 18:39
-
This technique works great. But I am trying to get the last text box on a form to also have a submit behavior on enter press. Even though the code above does not flag the event as handled, it seems that a key press defined in my XAML is ignored when the RegisterClassHandler is present. I would like to have an application wide default but also be able to define additional event behavior (or more accurately command bindings) for specific controls. – user2027080 Jan 02 '14 at 15:21
-
@user2027080 add an attached property such as AllowAdditionalHandling to those few controls and set it to true. Then in the code above, check for that attached property and don't mark the event handled accordingly. – StillLearnin Jan 03 '14 at 18:56
-
Thanks @StillLearnin for appriciation for my answer. Using AcceptsReturn property is smart way. – makwana.a Jul 31 '14 at 13:44
-
1This is real great solution. One central piece of code for the whole applicaton. Works like a charm! Thank you! – SQL Police Nov 01 '15 at 21:20
-
Had the exact use case when I had to add the functionality AFTER the application was completed. This worked exceptionally well! Thank you! – saurabhj Jun 11 '16 at 04:23
-
sample solution: using PreviewKeyDown in the stack panel. The Preview... is a bubble up so the event can be handled at a higher level. You may need to handle this differently for different element types, like button it seems should keep the enter key and not change focus on the enter key.
Here is the xaml:
<StackPanel PreviewKeyDown="StackPanel_PreviewKeyDown" >
<TextBox >
Hello
</TextBox>
<TextBox>
World
</TextBox>
<TextBox>
test
</TextBox>
</StackPanel>
And here is the code behind:
private void StackPanel_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox s = e.Source as TextBox;
if (s != null)
{
s.MoveFocus(new TraversalRequest( FocusNavigationDirection.Next));
}
e.Handled = true;
}
}
This is only a sandbox for proof of concept.
Happy Coding...

- 1,496
- 15
- 20
-
1Solid, short and simple answer. I think this is the best, universal approach – Tronald Nov 04 '14 at 16:51
Hope this help: use AttachedProperty http://madprops.org/blog/enter-to-tab-as-an-attached-property/
public class EnterKeyTraversal
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var ue = e.OriginalSource as FrameworkElement;
if (e.Key == Key.Enter)
{
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
private static void ue_Unloaded(object sender, RoutedEventArgs e)
{
var ue = sender as FrameworkElement;
if (ue == null) return;
ue.Unloaded -= ue_Unloaded;
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged));
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ue = d as FrameworkElement;
if (ue == null) return;
if ((bool)e.NewValue)
{
ue.Unloaded += ue_Unloaded;
ue.PreviewKeyDown += ue_PreviewKeyDown;
}
else
{
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
}
}
<StackPanel my:EnterKeyTraversal.IsEnabled="True">

- 4,771
- 2
- 46
- 53

- 396
- 1
- 17
Write This code in onstartup event of your application file
EventManager.RegisterClassHandler(GetType(TextBox), TextBox.KeyDownEvent, New RoutedEventHandler(AddressOf TextBox_KeyDown))
then define TextBox_KeyDown sub as
Private Sub TextBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs)
If e.Key = Key.Enter And TryCast(sender, TextBox).Tag <> "1" Then
' Creating a FocusNavigationDirection object and setting it to a
' local field that contains the direction selected.
Dim focusDirection As FocusNavigationDirection = FocusNavigationDirection.Next
' MoveFocus takes a TraveralReqest as its argument.
Dim request As New TraversalRequest(focusDirection)
' Gets the element with keyboard focus.
Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)
' Change keyboard focus.
If elementWithFocus IsNot Nothing Then
elementWithFocus.MoveFocus(request)
End If
End If
End Sub
I have used "tag" property of textbox for skip move focus. i.e. if some time you dont want to move to next control on enter key pressed (in the case of multiline text box where enter is required to create new line). Just set tag property to 1.

- 4,127
- 1
- 25
- 54

- 191
- 6
First that occured to add trigger to each element that will invoke when PreviewKeyDown
fires. Also add Dependency property and bind FrameworkElement
that you wont to bring focus at. Within trigger provide setting Focus
to binded element.

- 6,184
- 2
- 36
- 54
Using code-behind:
I came up with the below code. Note that it doesn't set e.Handled. Also, MoveFocus_Next doesn't return whether the move focus was successful, but rather if the argument is not null. You can add or remove types of controls to handle as required. The code was written for the MainWindow of the application, but handles other windows as well. You can also adapt the code for invocation from App_Startup event.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
public partial class MainWindow : Window
{
private bool MoveFocus_Next(UIElement uiElement)
{
if (uiElement != null)
{
uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
return true;
}
return false;
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(Window_PreviewKeyUp));
}
private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
IInputElement inputElement = Keyboard.FocusedElement;
if (inputElement != null)
{
System.Windows.Controls.Primitives.TextBoxBase textBoxBase = inputElement as System.Windows.Controls.Primitives.TextBoxBase;
if (textBoxBase != null)
{
if (!textBoxBase.AcceptsReturn)
MoveFocus_Next(textBoxBase);
return;
}
if (
MoveFocus_Next(inputElement as ComboBox)
||
MoveFocus_Next(inputElement as Button)
||
MoveFocus_Next(inputElement as DatePicker)
||
MoveFocus_Next(inputElement as CheckBox)
||
MoveFocus_Next(inputElement as DataGrid)
||
MoveFocus_Next(inputElement as TabItem)
||
MoveFocus_Next(inputElement as RadioButton)
||
MoveFocus_Next(inputElement as ListBox)
||
MoveFocus_Next(inputElement as ListView)
||
MoveFocus_Next(inputElement as PasswordBox)
||
MoveFocus_Next(inputElement as Window)
||
MoveFocus_Next(inputElement as Page)
||
MoveFocus_Next(inputElement as Frame)
)
return;
}
}
}
}

- 1,076
- 1
- 10
- 20