I have an WPF application which contains several TabItems. Each TabItem is different from each other, with a text and an icon.
This is how the TabItem´s style is defined:
<TabItem.Style>
<Style TargetType="TabItem">
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeafGrey.png"/>
<TextBlock Text="This is the heading" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="6,6,0,0" >
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#f5f7f8" Offset="0.0" />
<GradientStop Color="#c5d0dd" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Left" ContentSource="Header" Margin="5,2,0,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="Border">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ebedee" Offset="0.0" />
<GradientStop Color="#88a2bd" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeaf.png"/>
<TextBlock Text="This is the heading" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</TabItem.Style>
So instead of writing this XAML markup for each TabItem, I would like to define this style once in my ResourceDictionary, but with the Icon and the Text property as optional parameters. So I afterwards could define a TabItem like this:
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}" >
I´ve read that it isnt directly possible for a style to accept parameters like this, but it should be posible with some sort of binding. I havent found out exactly how though, so I really hope you can help.
Kind regards.
One way of doing it would be, if you have fixed number of TabItems
and you dont want to generate the TabItems
through ItemsSource
Binding
on TabControl. Then in your TabItem.Style
you can use Resource
keys to get the Text and Source like:
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="{DynamicResource Image1}"/>
<TextBlock Text="{DynamicResource Header}" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
and for your TabItems you can define these resources:
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}">
<TabItem.Resources>
<System:String x:Key="Header">TabItem1</System:String>
<System:String x:Key="Image1">image/1.png</System:String>
<System:String x:Key="Image2">image/2.png</System:String>
</TabItem.Resources>
</TabItem>
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}">
<TabItem.Resources>
<System:String x:Key="Header">TabItem2</System:String>
<System:String x:Key="Image1">image/3.png</System:String>
<System:String x:Key="Image2">image/4.png</System:String>
</TabItem.Resources>
</TabItem>
Also you will need to update your Style
to set the HeaderTemplate
instead of Header
<Style x:Key="CustomTabItem" TargetType="TabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="HeaderImage" Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeafGrey.png"/>
<TextBlock Text="{DynamicResource Header}" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}" Value="true">
<Setter TargetName="HeaderImage" Property="Source" Value="Images/IconLeaf.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="6,6,0,0" >
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#f5f7f8" Offset="0.0" />
<GradientStop Color="#c5d0dd" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Left" ContentSource="Header" Margin="5,2,0,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="Border">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ebedee" Offset="0.0" />
<GradientStop Color="#88a2bd" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You just need to set the TabItem.DataContext
to an object that contains values for your TextBlock
and Image
controls:
In code:
public class TabItemData
{
public string ImageSource { get; set; }
public string Heading { get; set; }
}
In your Style
in XAML:
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="{Binding ImageSource}"/>
<TextBlock Text="{Binding Heading}" VerticalAlignment="Center"
Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
In your view model:
public class TabControlViewModel
{
public TabControlViewModel()
{
TabItemData = new TabItemData() { Header = "Some header",
ImageSource = "Images/IconLeafGrey.png" };
}
public TabItemData TabItemData { get; set; }
}
In XAML:
<TabItem DataContext="{Binding TabItemData}">
...
</TabItem>
Of course, I've left out some initialisation of the data objects and the INotifyPropertyChanged
interface which you should implement, but I hope you get the idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With