Question

In my WPF 4.0 desktop-based application, I want to add an ability to traverse through window elements by pressing Tab-button.

Here is fragment of my XAML:

<!--main body layout-->
<StackPanel x:Name="BodyLayout"
        Style="{StaticResource Body_Block}">

    <!--teaser block-->
    <Grid x:Name="TeaserGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBlock Grid.Column="0"
               Grid.Row="0"
               Style="{StaticResource Body_Teaser_Centering}">
                <Hyperlink Style="{StaticResource Body_Teaser_Hyperlink}"
                       Focusable="True"
                       KeyboardNavigation.TabIndex="0"
                       Click="Call_WinOffences_Click">
                    <Image Source="Resources/teaser_offences.png"
                           Style="{StaticResource Body_Teaser_Image}" />
                    <LineBreak />
                    <TextBlock Text="Offences"
                            Style="{StaticResource Body_Title}" />
                </Hyperlink>
        </TextBlock>

        <TextBlock Grid.Column="1"
               Grid.Row="0"
               Style="{StaticResource Body_Teaser_Centering}">
            <Hyperlink Style="{StaticResource Body_Teaser_Hyperlink}"
                   Focusable="True"
                   KeyboardNavigation.TabIndex="1"
                   Click="Call_WinEvents_Click">
                <Image Source="Resources/teaser_events.png"
                       Style="{StaticResource Body_Teaser_Image}" />
                <LineBreak />
                <TextBlock Text="Events"
                       Style="{StaticResource Body_Title}" />
            </Hyperlink>
        </TextBlock>
    </Grid>
</StackPanel>

What exactly do I need? I want to open this window and by pressing first time on Tab keyboard to set focus on Hyperlink block (with Image and TextBlock) with TabIndex="0" and by second Tab pressing to switch focus on element with TabIndex="1", also I want to cycle this switches. In other words, I want that user could navigate through elements in my window by Tab keyboard as we are regular to do this in any other normal WinForms application.

What actually have I right now? When I press on Tab keyboard Hyperlinks don't get focus and I can't work with my window without the mouse.

Please, let me know, what I'm going wrong?

Was it helpful?

Solution

Update
I copied your sample code (except for the Styles which I didn't have) into a small project and it seems to be working fine for me. I can launch the Window, press Tab to Focus first Hyperlink, press Enter and the Click event is raised, press Tab again etc. The only thing I can think is that something in your Styles overrides this behavior. I uploaded my sample project here.

Note: I changed the Source for the Images so you'll have to change them back :)

Old post
There are two parts here. The first one is if a FrameworkElement is Focusable or not. The second one is TabIndex. TabIndex is in Control which derives from FrameworkElement and not all elements derive from Control, such as TextBlock, Rectangle etc. If you for some reason want to add TabIndex to such elements as well you you can use KeyboardNavigation.TabIndex instead. Here's an easy example with 6 controls with a Tab-Order set and 1 Rectangle isn't Focusable (since it isn't Focusable by default).

<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Button Grid.Row="0" Grid.Column="0"
            Content="Some Button"
            KeyboardNavigation.TabIndex="0"
            Margin="5"/>
    <TextBox Grid.Row="1" Grid.Column="0"
             Text="Some TextBox"
             KeyboardNavigation.TabIndex="2"
             Margin="5"/>
    <TextBox Grid.Row="2" Grid.Column="0"
             Text="Another TextBox"
             KeyboardNavigation.TabIndex="1"
             Margin="5"/>
    <TextBlock Grid.Row="0" Grid.Column="1"
               Text="Focusable TextBlock"
               Focusable="True"
               KeyboardNavigation.TabIndex="4"
               Margin="5"/>
    <Rectangle Grid.Row="1" Grid.Column="1"
               Fill="Blue"
               Margin="5"/>
    <Rectangle Grid.Row="2" Grid.Column="1"
               Fill="Red"
               Focusable="True"
               KeyboardNavigation.TabIndex="3"
               Margin="5"/>
</Grid>

OTHER TIPS

Maybe this will help: WPF TabStop / TabIndex in ItemsControl

TabIndex is the way you go here. When you hit tab to go through controls, it will go in the order of the TabIndex. These don't even need to be in sequential order -- 1, 2, 5 is the same as 1, 2, 3 if there is no 3 and 4 defined anywhere.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top