How to set header style in TabItem? - wpf

I've created in my Window.Resource a Style that hold the background of the selected TabItem. What I want achieve is set a custom height for the TabItem header, this is my Style:
<Window.Resources>
<ResourceDictionary>
<Style x:Key="CustomTabItem" TargetType="{x:Type TabItem}" BasedOn="{StaticResource MetroTabItem}">
<Setter Property="Width" Value="Auto"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Height" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" Background="Transparent">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Left"
ContentSource="Header"
Margin="10,3">
</ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="Border">
<Setter TargetName="Border" Property="Background" Value="Gainsboro" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="#FFC5C5C5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
usually I add the style to my TabControl like so:
<TabItem Tag="Tab1" Style="{StaticResource CustomTabItem}">
I just want set the header height for all the TabControls that have the CustomTabItem style, any suggestion?

You are making a confusion between TabControl and TabItem.
A TabControl has many TabItems.
Each TabItem is actually a Tab.
So the solutions are :
1 Set Style to all TabItems of all TabControls
A very simple way to apply the style is to remove the x:Key attribute of the TabItem style, and the style will apply to all TabItems
<!-- No x:Key="CustomTabItem" below -->
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource MetroTabItem}">
2 Set Style for all tabs of a TabControl
<TabControl ItemContainerStyle="{DynamicResource TabItemStyle1}" >
<TabItem Header="Hello">Hello content</TabItem>
<TabItem Header="Goodye">Goodbye content</TabItem>
</TabControl>
3 Set Style per TabItem
<TabControl>
<TabItem Style="{StaticResource CustomTabItem}" Header="Hello">Hello content</TabItem>
<TabItem Header="Goodye">Goodbye content</TabItem>
</TabControl>
Regards

Related

How to style tabitem same same height level top?

I custom to stlye tab item. but the first child dont same level with content area. picture. How to fix this. default tabcontrol thers border around border around tabitem.
<Application.Resources>
<Style x:Key="BlueOcean" TargetType="{x:Type TabControl}">
<Style.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Height" Value="50" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<StackPanel Name="Panel">
<ContentPresenter
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
</Style>
</Application.Resources>
TabControl View
<TabControl Style="{DynamicResource BlueOcean}" TabStripPlacement="Left">
<TabItem Header="Home" Content="Home Page" />
<TabItem Header="Settings" Content="Settings Page" />
</TabControl>

WPF - Using Control Template just on one element

My first steps in WPF and C# and i don't get it to work... :(
I have an application with two grids inside one window. I have to change the style of the first grid, so i started reading and reached using ControlTemplate.
My Grid now looks as i wanted it. But i only want that the first grid looks this way. the second one on the same page should have another style.
Is it possible to bind the controltemplate only on one grid. Maybe by name or soemthing identifying?
My ControlTemplate Code for now i have written in window.resources looks:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Margin="0,0,0,0"
Background="Black"
BorderBrush="Black"
BorderThickness="0,2,0,0"
CornerRadius="0,0,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="0,0,0,20"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#FF454E54" />
<Setter TargetName="Border" Property="Background" Value="#FF0A3651" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="White" />
<Setter TargetName="Border" Property="Background" Value="#FF454E54" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You could give the Style or ControlTemplate an x:Key ( <Style x:Key="key" TargetType="{x:Type TabItem}"> ) and apply it to the element you want by setting the element's Style or Template property like this:
<TabItem Style="{StaticResource key}">
A Style without an x:Key is implicit and will be applied to all elements whose type matches the specified TargetType of the Style.
Instead of writing your template under Window.Resources do it under your Grid.Resources
Try this. All this is doing is setting the style of the TabItem directly.
<TabItem> <!-- This is your TabItem control -->
<TabItem.Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<!-- ControlTemplate here -->
</Controltemplate
</Setter.Value>
</Setter>
</Style>
</TabItem.Style>
</TabItem>

WPF TabControl apply TabItem style insead of overriding it (while using ItemSource)

I have a parent TabControl with a custom TabItem style:
<TabControl ItemsSource="{Binding TabViewModels}" SelectedIndex="0" Padding="0,0,0,0" BorderThickness="0,0,0,0" Panel.ZIndex="1">
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}" >
<Border Name="Border" CornerRadius="6,6,0,0" Margin="0,0,2,2">
<ContentPresenter TextBlock.TextAlignment="Center" TextBlock.FontSize="14"
Height="40" Width="auto" Content="{Binding Path=TabName}" Margin="12,2,12,2"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="#00B6FA" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TabPanel">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</TabControl.Resources>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=. }"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Inside one of the Tabs of the parent TabControl I have a child TabControl.
The problem is that the child TabControl automaticly takes the custom TabItem style because I override it as you can see above. What I want is that the child TabControl takes the default windows style for the TabItems.
Is this possible to apply the custom Tab Item instead of override it and using an ItemSource?
You can specify the style for the nested TabControl via its Style property:
<TabControl Style="{DynamicResource ResourceKey={x:Type TabControl}}">
...
</TabControl>
The default style key is usually the type of the control, hence {x:Type TabControl}.
Update:
I assume that you're using so-called implicit style for tab items, which is defined in the top-level TabControl's resources dictionary. By implicit style I understand a style without a key and with TargetType specified. To apply a default style to TabItem controls within a particular nested TabControl, simply add an empty implicit style to its resources dictionary, like so:
<TabControl x:Name="OuterTabControl">
<TabControl.Resources>
<Style TargetType="TabItem">
<!-- your style definition -->
</Style>
</TabControl.Resources>
...
<TabControl x:Name="InnerTabControl">
<TabControl.Resources>
<Style TargetType="TabItem"/>
</TabControl.Resources>
</TabControl>
...
</TabControl>
To avoid un-styling nested tab controls, see AnjumSKhan's answer, which puts the outer control's style inside a trigger whose binding cleverly targets just the one control:
<TabControl.Resources>
<Style TargetType="TabItem">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TabControl, AncestorLevel=2}}" Value="{x:Null}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" Background="Red">
<ContentPresenter ContentSource="Header"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style> </TabControl.Resources>

How do I set TabControls TabItem header FontSize

I have a TabControl with a style that changes the FontSize of the Header of the TabItem. When I data bind the ItemsSource only the headers are affected by the FontSize. But when I use the same style on another TabControl and add the TabItems in XAML the FontSize is changed on all content in the TabItem. I want the style to work with both databound and non-databound TabItems.
<TabControl Style="{StaticResource VariablesTabControl}" ItemsSource="{Binding TabItems}">
...
</TabControl>
MainSkin.xaml:
<Style TargetType="TabControl" x:Key="VariablesTabControl">
<Setter Property="ItemContainerStyle" Value="{StaticResource VariableTabItem}" />
...
</Style>
<Style TargetType="TabItem" x:Key="VariableTabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel" MinHeight="30" MinWidth="120">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Left" ContentSource="Header" Margin="10,2" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}" />
<Setter Property="FontSize" Value="12" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Panel" Property="Background" Value="{StaticResource BackgroundMouseOver}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="{StaticResource SelectedBrush}" />
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}" />
<Setter Property="FontSize" Value="12" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Your problem is a result of Property Value Inheritance.
When you define the TabItems in xaml something like this:
<TabItem>
<TabItem.Header>
<TextBlock Text="TEST_HEADER1" />
</TabItem.Header>
<TextBlock Text="TEST_CONTENT1" />
</TabItem>
Both TextBoxes, the header, and the content are in the logical tree of the TabItem that means that any Inheritable property set on TabItem will be propagated down the tree to these TextBoxes.
The Foreground and FontSize are Inheritable.
If you have something like:
<TabItem Header="TEST_HEADER2">TEST_CONTENT2</TabItem>
you don't have any Elements in TabItem's logical tree, the elements for the Header and the content will be auto generated, and the properties will not be inherited.
But this type of declaring TabItem's is not very useful, you usually need some advanced XAML as the items content so I think the best way to solve this is by changing all those text properties in TabItem's HeaderTemplate, you can bind to TabItem's properties using the RelativeSource.

Styling TabItem when populated with ItemsSource

I'm using a WPF Tabcontrol populated with a collection using Itemssource.
<TabControl x:Name="_tabControl" ItemsSource="{Binding TabViewModelList}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding TabCaption}"/>
<Setter Property="Content" Value="{Binding TabContent}"/>
<Setter Property="IsSelected" Value="{Binding IsDefault}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
Now I want to set my TabItem-style in my App.xaml(or other resourcefile) like this:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Background="LightBlue"
BorderBrush="Black"
BorderThickness="1,1,1,1"
CornerRadius="6,6,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
..but the ItemContainerStyle, of course overrides the controltemplate.
How do I combine these two so I can load my tabcontrol dynamically and still be able to style my TabItems the way I want to?
Ok... Solved my own problem. Pretty obvious..
Named my template
<Style TargetType="{x:Type TabItem}" x:Key="TabItemTemplate">
Added a BasedOn property like this:
<Style TargetType="TabItem" BasedOn="{StaticResource TabItemTemplate}">
But if I could combine them into one template please let me know...

Resources