Gail Foad
Gail Foad

Reputation: 720

Using return/enter instead of tab skips an element in UWP app

I'd like to be able to use return/enter to get to the next TextBox in a UWP app. (I've included here a sample app, but my actual app has a lot of rows, so I don't want to have to add a KeyDown event to every TextBox if I can avoid it.)

I have added KeyDown="Grid_KeyDown" to my Grid then, if the user presses Enter, I call

FocusManager.TryMoveFocus(FocusNavigationDirection.Next)

It skips from the first element to the third element to the fifth. Tab works fine without skipping any elements.

Here's XAML:

<Page
    x:Class="CatApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CatApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" KeyDown="Grid_KeyDown">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition  Height="Auto"></RowDefinition>
            <RowDefinition  Height="Auto"></RowDefinition>
            <RowDefinition  Height="Auto"></RowDefinition>
            <RowDefinition  Height="Auto"></RowDefinition>
            <RowDefinition  Height="Auto"></RowDefinition>
            <RowDefinition  Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>

        <TextBlock Grid.Column="0" Grid.Row="0">First:</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="1">Second:</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="2">Third:</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="3">Fourth:</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="4">Fifth:</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="5">Sixth:</TextBlock>


        <TextBox Margin="10" Grid.Column="1" Grid.Row="0"  TabIndex="1" ></TextBox>
        <TextBox Margin="10" Grid.Column="1" Grid.Row="1"  TabIndex="2" ></TextBox>
        <TextBox Margin="10" Grid.Column="1" Grid.Row="2"  TabIndex="3" ></TextBox>
        <TextBox Margin="10" Grid.Column="1" Grid.Row="3"  TabIndex="4" ></TextBox>
        <TextBox Margin="10" Grid.Column="1" Grid.Row="4"  TabIndex="5" ></TextBox>
        <TextBox Margin="10" Grid.Column="1" Grid.Row="5"  TabIndex="6" ></TextBox>

    </Grid>
</Page>

Here's the code behind:

using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;

namespace CatApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
            {
                FocusManager.TryMoveFocus(FocusNavigationDirection.Next);
            }
        }
    }
}

Upvotes: 2

Views: 384

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39092

This is actually a known bug which has been in WinRT TextBox since Windows 8 and it appears it has been finally fixed in the Fall Creators Update (16299). If your app is targeting this version of Windows (or later), it should work properly.

To see what is happening put a breakpoint on the if in the event handler. When you press any key, the handler is executed once. But when you press Enter it is actually executed twice in a succession, which causes your focus to jump two lines.

The fix is quite easy - it is enough to mark the event as handled:

private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == Windows.System.VirtualKey.Enter)
    {
        FocusManager.TryMoveFocus(FocusNavigationDirection.Next);
        e.Handled = true;
    }
}

This will prevent the handler from executing twice and your app will work as expected :-) .

Upvotes: 1

Related Questions