Specified Tab Order is not being followed?

6k views Asked by At

Why isn't my XAML following the TabOrder I specified?

I currently have:

<DockPanel>
    <Grid DockPanel.Dock="Top">
        <UserControl TabIndex="0">
            <StackPanel Orientation="Horizontal">
                <ComboBox />
                <TextBox Text="Search Text" />
                <Button Content="Search" />
            </StackPanel>
        </UserControl>
        <ComboBox TabIndex="1" />
        <Separator />
        <TextBox TabIndex="3" Text="Save" />
        <TextBox TabIndex="4" Text="Cancel" />
    </Grid>
    <Grid>
        <ContentControl TabIndex="2" />
        <Popup />
    </Grid>
</DockPanel>

enter image description here

My TabOrder should go

  • Search ComboBox
  • Search Text
  • Search Button
  • Database ComboBox
  • ContentControl
  • Save Button
  • Cancel Button

But instead it goes

  • Search ComboBox
  • Search Text
  • Search Button
  • ContentControl
  • Database ComboBox
  • Save Button
  • Cancel Button

What do I have wrong with my TabOrder?

Edit

I found this SO answer which suggested making UserControl.IsTabStop="False", and binding it's Child control's TabIndex to UserControl.TabIndex, which partially works.

My TabOrder is now

  • Search ComboBox
  • Search Text
  • Search Button
  • Database ComboBox
  • Save Button
  • Cancel Button
  • ContentControl
3

There are 3 answers

0
Rachel On BEST ANSWER

Apparently by default, WPF reads all the controls, inside and outside UserControls, at the same tab level (unless specified otherwise). Since the controls inside the UserControl do not have a TabIndex specified, they get tabbed to last after the first tab cycle.

The workaround was to bind the TabIndex of the inner controls to the TabIndex of the UserControl

<DockPanel Margin="10" KeyboardNavigation.TabNavigation="Cycle">
    <Grid DockPanel.Dock="Top"
          local:GridProperties.ColumnCount="6"
          local:GridProperties.StarColumns="0">

        <TextBlock Text="Header" FontSize="20" FontWeight="Bold" />
        <ContentControl Grid.Column="1" TabIndex="0" IsTabStop="False" Content="{Binding SearchViewModel}" />

        <ComboBox Grid.Column="2" Margin="5" Width="100" />

        <Separator Grid.Column="3" Style="{StaticResource VerticalSeparatorStyle}" />

        <Button Grid.Column="4" TabIndex="3" Content="Save" Width="75" Margin="5" />
        <Button Grid.Column="5" TabIndex="4" Content="Cancel" Width="75" Margin="5" />
    </Grid>

    <Line HorizontalAlignment="Stretch" X2="1" Stretch="Fill" Stroke="Black" StrokeThickness="1" Margin="0,5" DockPanel.Dock="Top" />

    <Grid x:Name="ShellContentRoot">

        <!-- Current Page -->
        <ContentControl TabIndex="2" Content="{Binding CurrentAccount}" IsTabStop="False" />

        <!-- Search Results -->
        <local:PopupPanel local:PopupPanel.PopupParent="{Binding ElementName=ShellContentRoot}" />
    </Grid>
</DockPanel>

The only thing special about my SearchView is that the controls all set

TabIndex="{Binding Path=TabIndex, RelativeSource={RelativeSource 
    AncestorType={x:Type local:SearchView}}}"

Tab Order goes:

  • UserControl Search ComboBox
  • UserControl Search Text
  • UserControl Search Button
  • Database ComboBox
  • ContentControl
  • Save Button
  • Cancel Button
1
Joe Mancuso On

Try including KeyboardNavigation.TabNavigation="Local" in your parent DockPanel.

<DockPanel KeyboardNavigation.TabNavigation="Local">   

KeyboardNavigationMode

1
Joe Mancuso On

This works for me:

 <DockPanel  >
    <DockPanel DockPanel.Dock="Top">
         <UserControl TabIndex="0" KeyboardNavigation.TabNavigation="Local" DockPanel.Dock="Left">
            <StackPanel Orientation="Horizontal">
                <ComboBox />
                <TextBox Text="Search Text" />
                <Button Content="Search" />
            </StackPanel>
         </UserControl>
         <ComboBox TabIndex="1"  DockPanel.Dock="Left" />
         <Separator />
         <TextBox TabIndex="3" Text="Save"  DockPanel.Dock="Left"/>
         <TextBox TabIndex="4" Text="Cancel" DockPanel.Dock="Left"/>
    </DockPanel>
    <Grid DockPanel.Dock="Bottom">
          <ContentControl TabIndex="2"  Height="100" Width="100"/>
          <Popup />
    </Grid>
 </DockPanel>