Home > Back-end >  WPF: Can not select first TabItem in TabControl with nested TabControls
WPF: Can not select first TabItem in TabControl with nested TabControls

Time:02-02

I'm facing a strange issue with nested TabControls in WPF.

In my Home Window I need to put a TabControl inside another TabItem, in order to create different menu levels. Since I need to have no default-selected TabItem, I'm using TabControl.Loaded event like so:

    private void TabControl_Loaded(object sender, RoutedEventArgs e)
    {
        ((TabControl)sender).SelectedItem = null;
    }

The issue is: first TabItem of nested TabControl is not selectable, unless selecting the second one then clicking again on the first header.

I created a sample project to demonstrate the problem.

XAML:

<Window x:Class="TabControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TabControlTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TabControl Loaded="TabControl_Loaded">
            <TabItem>
                <TabItem.Header>
                    <Label Content="Menu 1" />
                </TabItem.Header>
                <Grid>
                    <TabControl Loaded="TabControl_Loaded">
                        <TabItem>
                            <TabItem.Header>
                                <Label Content="Sub-Menu 1" />
                            </TabItem.Header>
                            <Grid>
                                <Button Content="Button in subitem 1" Margin="82,131,553,89" />
                            </Grid>
                        </TabItem>
                        <TabItem>
                            <TabItem.Header>
                                <Label Content="Sub-Menu 2" />
                            </TabItem.Header>
                            <Grid>
                                <Button Content="Button in subitem 2" Margin="429,69,206,151" />
                            </Grid>
                        </TabItem>
                    </TabControl>
                </Grid>
            </TabItem>
            <TabItem>
                <TabItem.Header>
                    <Label Content="Menu 2" />
                </TabItem.Header>
                <Grid>
                    <Button Content="Button in Hello 2" Height="NaN" Margin="274,65,54,237" Width="NaN" />
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

If I disable the Loaded event, there are no issues.

Any help would be appreciated.

EDIT: I uploaded the sample project here.

CodePudding user response:

Instead of handling the Loaded event, I believe you can add an invisible TabItem to prevent the first "real" tab from being selected initially:

<TabControl>
    <TabItem Visibility="Collapsed" />
    <TabItem>
        <TabItem.Header>
            <Label Content="Menu 1" />
        </TabItem.Header>
        <Grid>
            <TabControl>
                <TabItem Header="" Visibility="Collapsed" />
                <TabItem>
                    <TabItem.Header>
                        <Label Content="Sub-Menu 1" />
                    </TabItem.Header>
                    <Grid>
                        <Button Content="Button in subitem 1" Margin="82,131,553,89" />
                    </Grid>
                </TabItem>
                <TabItem>
                    <TabItem.Header>
                        <Label Content="Sub-Menu 2" />
                    </TabItem.Header>
                    <Grid>
                        <Button Content="Button in subitem 2" Margin="429,69,206,151" />
                    </Grid>
                </TabItem>
            </TabControl>
        </Grid>
    </TabItem>
    <TabItem>
        <TabItem.Header>
            <Label Content="Menu 2" />
        </TabItem.Header>
        <Grid>
            <Button Content="Button in Hello 2" Height="NaN" Margin="274,65,54,237" Width="NaN" />
        </Grid>
    </TabItem>
</TabControl>

Another potential workaround would be to bind the TabControl to a source collection using the ItemsSource property.

CodePudding user response:

You could handle window.contentrendered and set the selectedindex to -1 on the outer tabcontrol:

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        tc.SelectedIndex = -1;
    }

I've named that tabcontrol tc, obviously:

<Grid>
    <TabControl x:Name="tc">
        <TabItem>

When I handle loaded on the outer tabcontrol, the same approach works.

    private void tc_Loaded(object sender, RoutedEventArgs e)
    {
        tc.SelectedIndex = -1;
    }
  • Related