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;
}