WPF Include controls of a TabItem into tab order

949 Views Asked by At

hopefully you can give me a hint what I'm doing wrong. I thought it would be quite easy to achive what I'm trying but I'm not able to solve my problem.

What do I want to do?

I have a form containing a couple of controls e.g. TextBoxes on the left side. On the right side I do have a TabControl with TabItems and on these items are also a couple of e.g. TextBoxes. The first TextBox on the left side will have the focus if I open the form. I entered the TabIndex in a way, that the first TextBox on the first TabItem (which is visible) should get the focus afterwards. But whatever I entered, always all TextBoxes on the left side received the focus, before the first TabItem got it. Please find below a sample code. What did I wrong?

<Grid Name="grid" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0">
        <TextBox Name="tb1" TabIndex="0" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
        <TextBox TabIndex="5" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
        <TextBox TabIndex="1" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
    </StackPanel>
    <TabControl Grid.Column="1" Height="Auto" Width="Auto" KeyboardNavigation.DirectionalNavigation="Contained">
        <TabItem Header="1">
            <StackPanel>
                <TextBox TabIndex="4" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox TabIndex="3" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox TabIndex="6" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
            <TextBox/>
            </StackPanel>
        </TabItem>
        <TabItem Header="2">
            <StackPanel>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
            </StackPanel>
        </TabItem>
    </TabControl>
</Grid>

Many thanks, Torsten

1

There are 1 best solutions below

1
On

The tab index will cycle within each TabItem, before it will attempt to go further (that is if TabIndex is defined to jump from one tab to another, in your case it is not). So what you are doing isn't going to work. As sucky as it might be, in your situation you will have to use code behind to set focus to an element outside the current TabItem if you want to break the inner tab cycle on that TabItem and jump out of it in the order that you describe . Here' I wrote a quick sample for this:

private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Tab) return;

        var textBox = (TextBox)sender;

        switch(textBox.Name)
        {
            case "tb1": 
                tab1.Focus(); 
                tb3.Focus();
                e.Handled = true;
                break;
            case "tb4": 
                tb5.Focus(); 
                e.Handled = true;
                break;
            case "tb5": 
                tab1.Focus(); 
                tb6.Focus(); 
                e.Handled = true;
                break;
        }
    }

 <Grid Name="grid" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0">
        <TextBox Name="tb0" KeyDown="TextBox_KeyDown" TabIndex="0" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
        <TextBox Name="tb5" KeyDown="TextBox_KeyDown" TabIndex="5" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
        <TextBox Name="tb1" KeyDown="TextBox_KeyDown" TabIndex="1" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
    </StackPanel>
    <TabControl Grid.Column="1" Height="Auto" Width="Auto" KeyboardNavigation.DirectionalNavigation="Contained">
        <TabItem x:Name="tab1" Header="1" KeyboardNavigation.DirectionalNavigation="Continue">
            <StackPanel>
                <TextBox Name="tb4" KeyDown="TextBox_KeyDown" TabIndex="4" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Name="tb3" KeyDown="TextBox_KeyDown" TabIndex="3" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Name="tb6" KeyDown="TextBox_KeyDown" TabIndex="6" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox/>
            </StackPanel>
        </TabItem>
        <TabItem x:Name="tab2" Header="2">
            <StackPanel>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
                <TextBox Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=TabIndex}"/>
            </StackPanel>
        </TabItem>
    </TabControl>
</Grid>