How can I hide a parent TabControl
until the child in one of its tabs is clicked on? Obviously, I need the child to be visible for the user to be able to click on it. The only thing that I have managed to come up with so far is a bit of a hack... I'm displaying an extra child item over the top of the TabControl
and then hiding it and showing the TabControl
upon clicking. Here is my hack:
XAML:
<Window x:Class="WpfApp1.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"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="600"
PreviewMouseLeftButtonUp="Grid_PreviewMouseLeftButtonUp">
<Window.Resources>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="300" />
<Setter Property="Height" Value="250" />
</Style>
</Window.Resources>
<Grid>
<TabControl Name="TabControl" Width="350" Height="300">
<TabItem Header="Original">
<Rectangle Fill="Red" />
</TabItem>
<TabItem Header="Modified">
<Rectangle Fill="Blue" />
</TabItem>
<TabControl.Style>
<Style TargetType="{x:Type TabControl}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsTabControlVisible}"
Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TabControl.Style>
</TabControl>
<Rectangle Fill="Red" Margin="0,22,0,0"
PreviewMouseLeftButtonUp="Rectangle_PreviewMouseLeftButtonUp">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}"
BasedOn="{StaticResource {x:Type Rectangle}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsTabControlVisible}"
Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</Window>
Code behind:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty IsTabControlVisibleProperty =
DependencyProperty.Register(nameof(IsTabControlVisible), typeof(bool),
typeof(MainWindow), null);
public bool IsTabControlVisible
{
get { return (bool)GetValue(IsTabControlVisibleProperty); }
set { SetValue(IsTabControlVisibleProperty, value); }
}
private void Rectangle_PreviewMouseLeftButtonUp(object sender,
MouseButtonEventArgs e)
{
IsTabControlVisible = true;
}
private void Grid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (!TabControl.IsMouseOver) IsTabControlVisible = false;
}
}
}
I've changed the content to plain Rectangle
s for simplicity.
How can I improve this situation? I don't like the idea of duplicating the child content to make this work. Does anyone have any better solutions?
You could, as @XAMIMAX mentioned, hide the TabControl
but not by its Opacity
(because setting it to 0 would hide the child too). The following XAML
is just a quick & dirty proof of concept by hiding all the Elements except the Child:
<TabControl Name="TabControl" Width="350" Height="300" BorderBrush="Transparent">
<!-- Content of the Tabcontrol -->
<TabItem Header="Original">
<Rectangle Fill="Red" />
</TabItem>
<TabItem Header="Modified" >
<Rectangle Fill="Blue" />
</TabItem>
<!-- Triggers for the TabControl -->
<TabControl.Triggers>
<!-- Set Borderbrush to Black when tab is clicked -->
<EventTrigger RoutedEvent="MouseDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Colors.Black}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<!-- Reset BorderBrush when Mouse leaves the TabControl (choose wathever condition you like to hide the tabs) -->
<EventTrigger RoutedEvent="MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Colors.Transparent}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</TabControl.Triggers>
<!-- Set "Style" of Container -->
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<!-- Hide Header -->
<Setter Property="Visibility" Value="Hidden"/>
<!-- Show header when Border of parent is Black (you can choose a different Property if you like) -->
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}}, Path=(BorderBrush).(SolidColorBrush.Color)}" Value="Black">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
The Tabcontrol has 2 Triggers: Setting the BorderBrush
to Black when someone clicks on the TabControl
and setting it to Transparent
when the MousePointer leaves the TabControl
. Theese two handle the visibility for the TabControl
itself. Note: Add additional Trigger
s if your Background
is different from the Color
behind the TabControl
.
The TabItem
has a Trigger
bound to the Color
of the TabControl
Border
. If the Color
is black, show the Header
of the TabItem
otherwise, hide them.