I have got a button with a ControlTemplate, this ControlTemplate has 2 different Control's with different background colours. I want to be able to change these colours using a new style which is BasedOn this main style.
Read the code and it should make more sense. For some reason though the new Style.Resources are not changing the background colours, they are still using the two defined in the main style.
How can I fix this?
Style BasedOn="{StaticResource ButtonIcoSmall}" TargetType="Button" x:Key="greenSmallButton">
<Style.Resources>
<SolidColorBrush Color="#FF8AB71C" x:Key="colour1" />
<SolidColorBrush Color="#FF72A000" x:Key="colour2" />
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource ButtonIcoSmall}" TargetType="Button" x:Key="greySmallButton">
<Style.Resources>
<SolidColorBrush Color="#FF434953" x:Key="colour1" />
<SolidColorBrush Color="#FF22252b" x:Key="colour2" />
</Style.Resources>
</Style>
<Style x:Key="ButtonIcoSmall" TargetType="Button">
<Style.Resources>
<SolidColorBrush Color="#FF434953" x:Key="colour1" />
<SolidColorBrush Color="#FF22252b" x:Key="colour2" />
</Style.Resources>
<Setter Property="FontFamily" Value="{StaticResource FontAwesome}" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Padding" Value="8" />
<Setter Property="Margin" Value="6" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<WrapPanel>
<Border Grid.Column="0"
CornerRadius="5 0 0 5"
BorderThickness="0"
Background="{StaticResource colour1}"
Name="buttonIcon">
<WrapPanel>
<ContentPresenter Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="{TemplateBinding Margin}" />
</WrapPanel>
</Border>
<Border Grid.Column="0"
CornerRadius="0 5 5 0"
BorderThickness="0"
Background="{StaticResource colour2}"
Name="buttonText" >
<TextBlock Text="{TemplateBinding Tag}"
FontSize="13"
Foreground="White"
Padding="{TemplateBinding Padding}" />
</Border>
</WrapPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding ElementName=buttonIcon}" TargetName="buttonText" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="#757b8d" />
<Setter Property="Foreground" Value="White" />-->
</Trigger>
</Style.Triggers>
</Style>
Two things:
You should move you main style above the derived styles. If you use BasedOn before the style that its basing itself on, it will not find it.
For the colors that you are changing, use a DynamicResource instead. This allows the two colors to be re-defined instead of using the defaults.
I got it working using the following code:
<Window x:Class="WpfApplication1.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"
x:Name="TestWindow">
<Window.Resources>
<Style x:Key="ButtonIcoSmall" TargetType="Button">
<Style.Resources>
<SolidColorBrush Color="#FF434953" x:Key="colour1" />
<SolidColorBrush Color="#FF22252b" x:Key="colour2" />
</Style.Resources>
<Setter Property="FontFamily" Value="{StaticResource FontAwesome}" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Padding" Value="8" />
<Setter Property="Margin" Value="6" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<WrapPanel>
<Border Grid.Column="0"
CornerRadius="5 0 0 5"
BorderThickness="0"
Background="{DynamicResource colour1}"
Name="buttonIcon">
<WrapPanel>
<ContentPresenter Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="{TemplateBinding Margin}" />
</WrapPanel>
</Border>
<Border Grid.Column="0"
CornerRadius="0 5 5 0"
BorderThickness="0"
Background="{DynamicResource colour2}"
Name="buttonText" >
<TextBlock Text="{TemplateBinding Tag}"
FontSize="13"
Foreground="White"
Padding="{TemplateBinding Padding}" />
</Border>
</WrapPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding ElementName=buttonIcon}" TargetName="buttonText" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="#757b8d" />
<Setter Property="Foreground" Value="White" />-->
</Trigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource ButtonIcoSmall}" TargetType="Button" x:Key="greenSmallButton">
<Style.Resources>
<SolidColorBrush Color="#FF8AB71C" x:Key="colour1" />
<SolidColorBrush Color="#FF72A000" x:Key="colour2" />
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource ButtonIcoSmall}" TargetType="Button" x:Key="greySmallButton">
<Style.Resources>
<SolidColorBrush Color="#FF434953" x:Key="colour1" />
<SolidColorBrush Color="#FF22252b" x:Key="colour2" />
</Style.Resources>
</Style>
</Window.Resources>
<Button Style="{StaticResource greenSmallButton}"/>
</Window>
Related
I can create a standard WPF window as follows, and all works fine.
<Window x:Class="WpfWindowStyleTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AllowsTransparency="True"
Background="Transparent"
ResizeMode="CanResizeWithGrip"
SizeToContent="WidthAndHeight"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="ClearType"
Topmost="True"
UseLayoutRounding="True"
WindowStyle="None">
<Grid>
<Border Background="LightGreen"
BorderBrush="Navy"
BorderThickness="2"
CornerRadius="4">
// window content here ...
</Border>
</Grid>
</Window>
However, my application requires a number of common components (way beyond a simple border) to be shared by all windows, so I tried to extract it into a common class.
public class BaseView: Window
{
static BaseView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BaseView), new FrameworkPropertyMetadata(typeof(BaseView)));
}
}
with the following style in generic.xaml
<Style BasedOn="{StaticResource {x:Type Window}}" TargetType="{x:Type local:BaseView}">
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="Topmost" Value="True" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BaseView}">
<Grid>
<AdornerDecorator>
<Border Background="LightGreen"
BorderBrush="Navy"
BorderThickness="2"
CornerRadius="4">
<ContentPresenter Margin="24" HorizontalAlignment="Left" />
</Border>
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This works fine.
However, when I add another property setter to the style
<Setter Property="ResizeMode" Value="CanResizeWithGrip" />
The whole control template is ignored, and just the specified window content is displayed (in an empty, resizable window).
Is there any way around this?
Your issue depends on the standard Window style; take a look:
<Style x:Key="{x:Type Window}" TargetType="{x:Type Window}">
<Setter Property="Control.Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Control.Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border Background="{TemplateBinding Control.Background}" BorderBrush="{TemplateBinding Control.BorderBrush}" BorderThickness="{TemplateBinding Control.BorderThickness}">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Window.ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Control.Template" Value="{StaticResource ħ}" />
</Trigger>
</Style.Triggers>
</Style>
As you can see, if the ResizeMode is set to CanResizeWithGrip, a trigger changes the Window's template.
A simple solution could be adding a ResizeGrip to your template and avoing that your style inherits from the default one. Something like:
<Style TargetType="{x:Type local:BaseView}">
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="Topmost" Value="True" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanResizeWithGrip" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BaseView}">
<Grid>
<AdornerDecorator>
<Border Background="LightGreen"
BorderBrush="Navy"
BorderThickness="2"
CornerRadius="4">
<ContentPresenter Margin="24" HorizontalAlignment="Left" />
</Border>
</AdornerDecorator>
<ResizeGrip Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsTabStop="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I hope it can help you.
All,
I am trying to set up a Template for a Window. What I want is to change the margin and the border thickness depending upon the state of the window. I am trying to do it using Trigger, but when I run the application, triggers don't fire. My question is, how can I make the triggers fire when the window state is changed?
The XAML I have is (I have removed most of the code to keep the posting simple):
<Window x:Class="WpfApplication1.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:WpfApplication1" Background="#FFE8E8E8"
Style="{DynamicResource ChromeWindowStyle}"
mc:Ignorable="d"
Title="BaseWindow" Width="500" Height="300">
<WindowChrome.WindowChrome>
<WindowChrome ResizeBorderThickness="6" CaptionHeight="0" GlassFrameThickness="0" />
</WindowChrome.WindowChrome>
<Window.Resources>
<Style x:Key="ChromeWindowStyle" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="#FFE8E8E8"/>
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border x:Name="MainBorder" Background="White" BorderBrush="Gray" BorderThickness="1">
<DockPanel LastChildFill="True">
<Border Height="30" DockPanel.Dock="Top">
<DockPanel LastChildFill="False">
<TextBlock Text="Heading" DockPanel.Dock="Left" VerticalAlignment="Center" />
<Button x:Name="CloseButton" Content="Close" DockPanel.Dock="Right" />
<Button x:Name="MaximizeButton" Content="Max" DockPanel.Dock="Right" />
<Button x:Name="MinButton" Content="Min" DockPanel.Dock="Right"/>
</DockPanel>
</Border>
<AdornerDecorator DockPanel.Dock="Bottom">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
</AdornerDecorator>
</DockPanel>
</Border>
<!--This piece wont trigger - start -->
<ControlTemplate.Triggers>
<Trigger Property="WindowState" Value="Normal">
<Setter Property="Margin" Value="8" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
<Trigger Property="WindowState" Value="Maximized">
<Setter Property="Margin" Value="8" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</ControlTemplate.Triggers>
<!--This piece wont trigger - end -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
</Grid>
</Window>
Your ControlTemplate.Triggers are trying to set properties on the ControlTemplate itself, which in-and-of itself is not a visual element. They need to explicitly specify the name of the Border control:
<ControlTemplate.Triggers>
<Trigger Property="WindowState" Value="Normal">
<Setter TargetName="MainBorder" Property="Margin" Value="8" />
<Setter TargetName="MainBorder" Property="BorderThickness" Value="1" />
</Trigger>
<Trigger Property="WindowState" Value="Maximized">
<Setter TargetName="MainBorder" Property="Margin" Value="8" />
<Setter TargetName="MainBorder" Property="BorderThickness" Value="0" />
</Trigger>
</ControlTemplate.Triggers>
EDIT: Oh ok, I'm still on 4.5.1, maybe that's new behavior? In that case I'd go the other way i.e. put DataTriggers on the border control itself:
<Style x:Key="ChromeWindowStyle" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderBrush="Gray">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Margin" Value="8" />
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=WindowState}" Value="Maximized">
<Setter Property="Margin" Value="8" />
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<DockPanel LastChildFill="True">
<Border Height="30" DockPanel.Dock="Top">
<DockPanel LastChildFill="False">
<TextBlock Text="Heading" DockPanel.Dock="Left" VerticalAlignment="Center" />
<Button x:Name="CloseButton" Content="Close" DockPanel.Dock="Right" />
<Button x:Name="MaximizeButton" Content="Max" DockPanel.Dock="Right" Click="MaximizeButton_Click"/>
<Button x:Name="MinButton" Content="Min" DockPanel.Dock="Right"/>
</DockPanel>
</Border>
<AdornerDecorator DockPanel.Dock="Bottom">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
</AdornerDecorator>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm trying to style a button, but it ends up not showing when I apply the custom style, only its content (the button's text) is visible. This is how I declare my style:
<Color x:Key="NormalColor" A="255" R="60" G ="158" B="184"/>
<Color x:Key="HoverColor" A="255" R="74" G ="177" B="204"/>
<Color x:Key="PressedColor" A="255" R="26" G ="115" B="138"/>
<SolidColorBrush x:Key="NormalBrush" Color="{StaticResource NormalColor}" />
<SolidColorBrush x:Key="HoverBrush" Color="{StaticResource HoverColor}" />
<SolidColorBrush x:Key="PressedBrush" Color="{StaticResource PressedColor}" />
<Style x:Key="FlatButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="Background" Value="{StaticResource NormalBrush}"/>
<Setter Property="Foreground" Value="#000000"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="Content"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource HoverBrush}" />
<Setter Property="Foreground" Value="#000000" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource PressedBrush}" />
<Setter Property="Foreground" Value="#000000" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{StaticResource NormalBrush}" />
<Setter Property="Foreground" Value="#000000" />
<Setter Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And here is how I use it:
<Button Content="Connect" Command="model:GlobalCommands.ConnectToDBCommand" Style="{StaticResource FlatButton}"/>
Can anyone tell me where I went wrong with this?
Thank you!
There is nothing in your ControlTemplate that would use Background. Put your ContentPresenter inside Border (for example) and use TemplateBinding to bind its Background
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="Content"/>
</Border>
Adding to #dkozl's answer, you should add TemplateBindings to any properties within the Button.ControlTemplate that you may want to set from outside the Button.ControlTemplate:
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding
BorderThickness}" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
Then you could do this:
<Button Content="Connect" Command="model:GlobalCommands.ConnectToDBCommand"
Style="{StaticResource FlatButton}" BorderBrush="Blue" BordeThickness="5" />
Above is an image of my listboxitem.
I am wondering whether it is possible to remove the rectangle that surronds the ellipse.
Padding and BorderThicknes are 0 already.
I use this styling:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem"> ...
<Style.Triggers>
<DataTrigger Binding="{Binding Data}" Value="ellipse">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Ellipse Fill="{Binding Brush}" Stroke="Black"/>
<TextBlock Text="{Binding Int}" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
I tried this:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
Then the items are not selectable any more.
You should create control template for ListBoxItem. Then you can change background of ListBoxItem.
<Window.Resources>
<Style x:Key="{x:Type ListBoxItem}"
TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border"
BorderThickness="2"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="{x:Static Brushes.Transparent}" />
<Setter TargetName="Border"
Property="BorderBrush"
Value="{x:Static Brushes.WhiteSmoke}" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{x:Static Brushes.Transparent}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox Margin="5" ItemsSource="{Binding Path=Datas}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Ellipse Width="30"
Height="30"
Fill="{Binding Path=EllipseBrush}"/>
<TextBlock Text="{Binding Path=Number}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Sample you can download here
It seems to me that the 'Rectangle' that you're talking about is just the ListBoxItem.Background. It also looks like the default selection Color used in the ListBox control. If that's what it is, you can easily hide this by setting some property values in a local Resources section. Try adding these to your ListBox.Resources section:
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
In the second code there is a textBlock with the text "Mina övningar"
How can I change the text color to black when the tabItem is selected?
style:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Margin="0,0,0,13" CornerRadius="5" >
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Top" HorizontalAlignment="Center" ContentSource="Header" Margin="9"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF9F7FD" Offset="0.432" />
<GradientStop Color="#FFECF7FD" Offset="0.433" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="ContentSite" Property="Margin" Value="9,12,9,9" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
tabitem:
<TabItem Background="White">
<TabItem.Header>
<StackPanel Orientation="Vertical">
<Image Height="32" Source="/Glosboken;component/Images/library bookmarked.png" />
<TextBlock Text="Mina övningar" Margin="0,0,0,0" VerticalAlignment="Center" Foreground="White" />
</StackPanel>
</TabItem.Header>
<Grid>
<ListBox Height="216" Name="bookslist" VerticalAlignment="Top" Background="White" BorderBrush="White" Foreground="White" SelectedIndex="0" Margin="0,0,129,0" />
</Grid>
</TabItem>
One solution is to use a separate style for this situation:
<Style x:Key="TabItemText" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="False">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
and then replace:
Foreground="White"
with:
Style="{StaticResource TabItemText}"
in the TextBlock.
I did this by naming the ContentPresenter and targeting it in the trigger.
This way it keeps everything for the TabItem style in one place.
Complete Example:
<Window x:Class="TabControlText.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="TabItemStyle1" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="Border" BorderThickness="1,1,1,0" CornerRadius="5,5,0,0"
Padding="25,5,25,5" Margin="0,0,0,0" BorderBrush="Gainsboro">
<ContentPresenter x:Name="ContentSite" ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="TextElement.Foreground" TargetName="ContentSite" Value="White"/>
<Setter TargetName="Border" Property="Background" Value="Black"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="TextElement.Foreground" TargetName="ContentSite" Value="Black"/>
<Setter TargetName="Border" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl>
<TabItem Header="Tab 1" Style="{DynamicResource TabItemStyle1}" />
<TabItem Header="Tab 2" Style="{DynamicResource TabItemStyle1}" />
<TabItem Header="Tab 3" Style="{DynamicResource TabItemStyle1}" />
<TabItem Header="Tab 4" Style="{DynamicResource TabItemStyle1}" />
</TabControl>
</Grid>
I extended Scott Solmer's great code by making it a resource dictionary because I needed this TabItem styling application wide.
So add new TabItemStyles.xaml under the Resources Dictionary folder which was called "Resources" :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ColoredTabsStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="Border" BorderThickness="1,1,1,0" CornerRadius="5,5,0,0"
Padding="25,5,25,5" Margin="0,0,0,0" BorderBrush="Gainsboro">
<ContentPresenter x:Name="ContentSite" ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="TextElement.Foreground" TargetName="ContentSite" Value="White" />
<Setter TargetName="Border" Property="Background" Value="Black" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="TextElement.Foreground" TargetName="ContentSite" Value="Black" />
<Setter TargetName="Border" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I changed my app.xaml to know about the new resource dictionary. WARNING - adjust the source and component locations for your application:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/TruPredict;component/Resources/TabItemStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
Then I used style in the actual screen everywhere in the application I needed. Unlike Scott, I prefer using StaticResource rather than DynamicResource unless I have to.:
<TabControl>
<TabItem Header="Tab1" Style="{StaticResource ColoredTabsStyle}">
<TabItem Header="Tab2" Style="{StaticResource ColoredTabsStyle}">
<TabItem Header="Tab3" Style="{StaticResource ColoredTabsStyle}">
<TabControl>