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>
My TabOrder should go
But instead it goes
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
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: