On my WPF course someone asked how we could move the focus to the next control on the page when the enter key is pressed on a textbox. Let’s suppose we have a data entry form which mostly is consisted of TextBox (or alike) controls.

A lot of users are used to press enter when they are finished entering a field, but we need to change the focus to the next control when this happens so user won’t have to press tab key. Let’s see how this would be done in WinForms world. There are a couple of ways to tackle this:

  • Create a custom control, e.g. a custom TextBox derived control and listen to keydown event and move the focus to the next control then. Existing controls in your toolbelt also may provide this functionality out of the box. In fact, DevExpress controls have this feature and it is as easy as setting a property.

  • Create a Property Extender control and by setting the property on the control, we change the focus when the enter key is pressed. This is an elegant solution, but you also need to remember to set the property on all the controls.

In WPF world, things are a little different. With the power of “Preview” events, you can achieve this pretty easily by listening to the KeyDown event of your Window (or root object) instead of each Textboxes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<Window x:Class="EnterFocus.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="300" Height="180" Margin="10" >
<Grid PreviewKeyDown="OnContainerKeyDown">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock Text="Firstname: " TextAlignment="Right" VerticalAlignment="Center" Grid.Row="0" />
<TextBlock Text="Lastnmae: " TextAlignment="Right" VerticalAlignment="Center" Grid.Row="1" />
<TextBlock Text="Address: " TextAlignment="Right" VerticalAlignment="Center" Grid.Row="2" />
<TextBlock Text="Phone: " TextAlignment="Right" VerticalAlignment="Center" Grid.Row="3" />

<TextBox Grid.Column="1" Grid.Row="0" Margin="2" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="2" />
<TextBox Grid.Column="1" Grid.Row="2" Margin="2" />
<TextBox Grid.Column="1" Grid.Row="3" Margin="2" />

<Button Grid.Row="4" Grid.ColumnSpan="2" Content="Save" Width="100" Margin="10" />
</Grid>
</Window>

Notice the PreviewKeyDown event is on the Grid (root container) control and nothing is specified on TextBox controls. Moving the focus to another control is a little bit different compared to WinForms:

1
2
3
4
5
6
7
8
9
10
11
12
private void OnContainerKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter)
{
var element = e.Source as TextBox;
if (element != null)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
element.MoveFocus(request);
}
}
}