Reuse a button in WFP application - wpf

I'm developing my first win8 application. And I need to create a log off button on several pages.
In general this is a button with some text and image inside.
What approach should I choose: crate a template, a resource or style?

You can use style to reuse a button. The style should define its template and a resource is just available based on where it is defined.
Sample of a style targeting the button that you defined with x:Key to be reused everywhere else. If you did not specify x:Key and the style is defined in the Application Resources then it will apply the style to all of your buttons.
<Style x:Key="CustomStyleButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="#373737" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="15" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<Grid>
<Path x:Name="PathIcon" Width="15" Height="25" Stretch="Fill" Fill="#4C87B3" HorizontalAlignment="Left" Margin="17,0,0,0" Data="F1 M 30.0833,22.1667L 50.6665,37.6043L 50.6665,38.7918L 30.0833,53.8333L 30.0833,22.1667 Z "/>
<ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#E59400" />
<Setter Property="Foreground" Value="White" />
<Setter TargetName="PathIcon" Property="Fill" Value="Black" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="OrangeRed" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Sample usage
<Button Width="200" Height="50" Style="{StaticResource CustomStyleButton}" VerticalAlignment="Top" Margin="0,20,0,0" />
<Button.Content>
<StackPanel>
<TextBlock Text="Watch Now" FontSize="20" />
<TextBlock Text="Duration: 50m" FontSize="12" Foreground="Gainsboro" />
</StackPanel>
</Button.Content>

Related

Code for creating icons

This question is probably stupid but I have googled for some time now and didn't find any answers.
I found a post about button styles in where someone added this code example:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#373737" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="15" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<Grid>
<Path x:Name="PathIcon" Width="15" Height="25" Stretch="Fill" Fill="#4C87B3" HorizontalAlignment="Left" Margin="17,0,0,0" Data="F1 M 30.0833,22.1667L 50.6665,37.6043L 50.6665,38.7918L 30.0833,53.8333L 30.0833,22.1667 Z "/>
<ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#E59400" />
<Setter Property="Foreground" Value="White" />
<Setter TargetName="PathIcon" Property="Fill" Value="Black" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="OrangeRed" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
This creates a button with an arrow on the left side of the button.
My question is: How is this data called?
Data="F1 M 30.0833,22.1667L 50.6665,37.6043L 50.6665,38.7918L 30.0833,53.8333L 30.0833,22.1667 Z "
EDIT:
I tried to export some icons. Sometimes I get usable Path.Data and sometimes I get something like this:
<!-- Created with Ai->XAML Export Plug-In Version 0.2 (PC/64) -->
<!-- By Mike Swanson (http://blog.mikeswanson.com/) -->
<Viewbox Width="111.000" Height="81.000"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Width="111.000" Height="81.000">
</Canvas>
</Viewbox>
Can I even use this and how?

Two buttons with TextBox in the middle, ControlTemplate

Having a problem with this style, I can't find a way to make the following layout:
So I need just the corners of the buttons on the outside to be rounded, but I don't know how to do this, as the ControlTemplate for the buttons can't have the CornerRadius property as I would have to round all the corners.
This is the style I have got now, it just produces the style as seen above but with no CornerRadius.
P.S. There does seem to be an issue with the far left button going behind the TextBox which I noticed when the TextBox was slightly transparent. Not sure what is causing this!
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Controls">
<Style TargetType="{x:Type local:NumericUpDown}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:NumericUpDown}">
<ControlTemplate.Resources>
<Style TargetType="Button">
<Setter Property="Padding" Value="5" />
<Setter Property="Background" Value="#434953" />
<Setter Property="MinWidth" Value="30" />
<Setter Property="MinHeight" Value="25" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
<Border x:Name="Border1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#434953">
<ContentPresenter Content="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border1" Property="Background" Value="#834953"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ControlTemplate.Resources>
<Border Focusable="{TemplateBinding Focusable}">
<DockPanel Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
VerticalAlignment="Center"
Focusable="False">
<Button x:Name="PART_DecreaseButton" DockPanel.Dock="Left">
<Button.Content>
<Path Data="M0,0 L1,0 0.5,1Z"
Fill="White"
Width="8"
Height="6"
Stretch="Fill"/>
</Button.Content>
</Button>
<Button x:Name="PART_IncreaseButton" DockPanel.Dock="Right">
<Button.Content>
<Path Data="M0,1 L1,1 0.5,0Z"
Width="8"
Height="6"
Fill="White"
Stretch="Fill" />
</Button.Content>
</Button>
<TextBox x:Name="PART_TextBox"
Foreground="White"
HorizontalContentAlignment="Center"
HorizontalAlignment="Stretch"
Background="#22252b"
BorderThickness="0"
MinWidth="35" IsEnabled="True" Focusable="False" />
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="PART_DecreaseButton">
<Setter Property="Background" Value="Red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
you can encapsulate the whole thing and apply opacity mask like in this tutorial
http://wpf.2000things.com/2012/05/11/556-clipping-to-a-border-using-an-opacity-mask/

WPF ControlTemplate Trigger

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>

WPF Submenu styling

If I add a submenu to a menu item, then the submenu is not being styled properly. One can only style the menuitem at this point, and not the actual sub menu. Hence one can't replace the IsMouseOver styling which then just defaults to whatever theme is enabled on windows.
How can one style the submenu?
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Background" Value="#0f3c5a"></Setter>
<Setter Property="Foreground" Value="White"></Setter>
<Style.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" Value="Black"></Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightGray"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<!--Here is where you change the border thickness to zero on the menu-->
<Border BorderThickness="0" x:Name="Border" >
<StackPanel ClipToBounds="True" Orientation="Vertical"
IsItemsHost="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="#5082a4" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and then something like this for the menu
<ContextMenu Closed="ContextMenu_Closed" >
<MenuItem Command="k:Window1.NewCommand" >
<MenuItem Command="k:Window1.DeleteCommand"/>
</MenuItem>
...
Everything on the NewCommand layer is styled properly, going inside NewCommand to view DeleteCommand the MenuItem itself is styled properly, but the actual menu is defaulting to the Windows theme styling and I see no way over overwriting that so far. The most important part is to get the IsMouseOver of submenu's to maintain the same look and feel as the main menu structure.
As promised, here's the code. Thanks for your help Jay, lead me in the right direction to finally find an answer on MSDN http://msdn.microsoft.com/en-us/library/ms752296.aspx MenuItem and ContextMenu control the styling for the base menu, and the other two are for the submenu items. Jay's way may have worked, but I couldn't get it to unfortunately. This works perfectly though, and probably allows for much more control over the submenus styling.
<UserControl.Resources>
<!-- Separator -->
<Style TargetType="{x:Type Separator}"
x:Key="SeparatorStyle">
<Setter Property="Height"
Value="1" />
<Setter Property="Background"
Value="#0f3c5a" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Separator}">
<Rectangle Height="{TemplateBinding Height}"
Fill="White" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--Outer menu items-->
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Background"
Value="#0f3c5a"></Setter>
<Setter Property="Foreground"
Value="White"></Setter>
<Style.Triggers>
<Trigger Property="IsHighlighted"
Value="True">
<Setter Property="Background"
Value="Black"></Setter>
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="LightGray"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<!-- Outer menu -->
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<!--Here is where you change the border thickness to zero on the menu-->
<Border BorderThickness="0"
x:Name="Border"
Background="Transparent">
<StackPanel ClipToBounds="True"
Orientation="Vertical"
IsItemsHost="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="#0f3c5a" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- SubmenuItem -->
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}"
TargetType="{x:Type MenuItem}">
<Border Name="Border">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="Icon" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="Shortcut" />
<ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>
<ContentPresenter Name="Icon"
Margin="6,0,6,0"
VerticalAlignment="Center"
ContentSource="Icon" />
<Border Name="Check"
Width="13"
Height="13"
Visibility="Collapsed"
Margin="6,0,6,0"
Background="#0f3c5a"
BorderThickness="1"
BorderBrush="#5082a4">
<Path Name="CheckMark"
Width="7"
Height="7"
Visibility="Hidden"
SnapsToDevicePixels="False"
Stroke="#5082a4"
StrokeThickness="2"
Data="M 0 0 L 7 7 M 0 7 L 7 0" />
</Border>
<ContentPresenter Name="HeaderHost"
Grid.Column="1"
ContentSource="Header"
RecognizesAccessKey="True" />
<TextBlock x:Name="InputGestureText"
Grid.Column="2"
Text="{TemplateBinding InputGestureText}"
Margin="5,2,0,2"
DockPanel.Dock="Right" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon"
Value="{x:Null}">
<Setter TargetName="Icon"
Property="Visibility"
Value="Hidden" />
</Trigger>
<Trigger Property="IsChecked"
Value="true">
<Setter TargetName="CheckMark"
Property="Visibility"
Value="Visible" />
</Trigger>
<Trigger Property="IsCheckable"
Value="true">
<Setter TargetName="Check"
Property="Visibility"
Value="Visible" />
<Setter TargetName="Icon"
Property="Visibility"
Value="Hidden" />
</Trigger>
<Trigger Property="IsHighlighted"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="#5082a4" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="#0f3c5a" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- SubmenuHeader -->
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}"
TargetType="{x:Type MenuItem}">
<Border Name="Border">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="Icon" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="Shortcut" />
<ColumnDefinition Width="13" />
</Grid.ColumnDefinitions>
<ContentPresenter Name="Icon"
Margin="6,0,6,0"
VerticalAlignment="Center"
ContentSource="Icon" />
<ContentPresenter Name="HeaderHost"
Grid.Column="1"
ContentSource="Header"
RecognizesAccessKey="True" />
<TextBlock x:Name="InputGestureText"
Grid.Column="2"
Text="{TemplateBinding InputGestureText}"
Margin="5,2,2,2"
DockPanel.Dock="Right" />
<Path Grid.Column="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 0 7 L 4 3.5 Z"
Fill="#0f3c5a" />
<Popup Name="Popup"
Placement="Right"
HorizontalOffset="-4"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border Name="SubmenuBorder"
SnapsToDevicePixels="True"
Background="#0f3c5a"
BorderBrush="#0f3c5a"
BorderThickness="1">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon"
Value="{x:Null}">
<Setter TargetName="Icon"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<Trigger Property="IsHighlighted"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="#5082a4" />
</Trigger>
<Trigger SourceName="Popup"
Property="Popup.AllowsTransparency"
Value="True">
<Setter TargetName="SubmenuBorder"
Property="CornerRadius"
Value="4" />
<Setter TargetName="SubmenuBorder"
Property="Padding"
Value="0,3,0,3" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="#0f3c5a" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
How are you applying your styles?
Typically, if you define as style in a "high" or "outer" element's Resources, and give it no key, it will apply to all items of the target type below.
Are you doing this and seeing unexpected behaviour, or are you attempting to define/apply styles in-line at each level?
edit 1
Looking at your XAML, I think the issue is that you are styling ContextMenu, but menus below that are of type Menu. The first thing I'd try is to just change the TargetType attribute for the Style to Menu. See if that gets applied at all levels. If not, I'd change it back and add another Style targeting Menu and see if that one gets applied to the submenu.
edit 2
Okay, I think I've got your answer. The submenu is actually a MenuItem, which is obvious when looking at the XAML instead of the result. The template and styling that you're setting on the ContextMenu must also be set on any MenuItem that is a submenu. I tried it out and created a style that targets MenuItem with a control template and trigger for IsMouseOver and it appeared to do what you're trying.
To not duplicate the templates, you're better off creating one with both PART_Popup and arrow for the submenu, but hide the error until you're triggered with Role being SubmenuHeader.

How Do I Change The Text Foreground of a WPF TabItem With Nested Text?

I'm looking to have the foreground of the text of a TabItem change whenever the tab becomes active. I was using the following, which was working fine until I changed the type of content being displayed in the tab:
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Header="TabItem" Style="{DynamicResource SidebarTab}" />
</TabControl>
<Style x:Key="SidebarTabForegroundStyleSelected">
<Setter Property="TextBlock.Foreground" Value="White" />
</Style>
<Style x:Key="SidebarTabForegroundStyle">
<Setter Property="TextBlock.Foreground" Value="Black" />
</Style>
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Padding" Value="10,12,2,12" />
<Setter Property="BorderThickness" Value="0,1,0,1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Padding="{TemplateBinding Padding}"
Name="tab"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{StaticResource SidebarTabBorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter Style="{StaticResource SidebarTabForegroundStyle}" Name="content" ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrushSelected}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrushSelected}" />
<Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyleSelected}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrush}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrush}" />
<Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyle}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When I changed the TabItem to:
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Height="16" Source="..\..\Icons\cog.png" />
<TextBlock Text="TabItem" Margin="5,0,0,0" VerticalAlignment="Center" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl>
The foreground of the text no longer turns to white when the tab is selected and back to black when the tab is no longer selected. Everything else still works correctly.
Does anyone know if there is a way to accomplish changing the color of the foreground in the XAML above?
Move the trigger from the control template to the style:
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="SidebarTabBackgroundBrushSelected" Color="Gray"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBorderBrushSelected" Color="Blue"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBackgroundBrush" Color="LightGray"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBorderBrush" Color="Green"></SolidColorBrush>
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Padding" Value="10,12,2,12" />
<Setter Property="BorderThickness" Value="0,1,0,1" />
<Setter Property="Foreground" Value="Blue"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Padding="{TemplateBinding Padding}"
Name="tab"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{StaticResource SidebarTabBorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter Name="content"
ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrushSelected}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrushSelected}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrush}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Header="TabItem 1" Style="{DynamicResource SidebarTab}" />
<TabItem Style="{DynamicResource SidebarTab}" >
<TabItem.Header>
<StackPanel>
<TextBlock Text="a"></TextBlock>
<TextBlock Text="b"></TextBlock>
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem Header="TabItem 3" Style="{DynamicResource SidebarTab}" />
</TabControl>
</Grid>
It looks like the issue is coming up because you are setting the wrong property:
<Style x:Key="SidebarTabForegroundStyleSelected">
<Setter Property="TextBox.Foreground" Value="White" />
</Style>
<Style x:Key="SidebarTabForegroundStyle">
<Setter Property="TextBox.Foreground" Value="Black" />
</Style>
You need to be setting TextElement.Foreground or TextBlock.Foreground
Also, since it is an inherited property, you can just set the AttachedProperty directly on the TabItems, you don't need to assign it specifically to the content.
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="TextElement.Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TabControl.ItemContainerStyle>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Height="16"
Source="..\..\Icons\cog.png" />
<TextBlock Text="TabItem"
Margin="5,0,0,0"
VerticalAlignment="Center" />
</StackPanel>
</TabItem.Header>
Item 1
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Text="Tab 2" />
</TabItem.Header>
Item 2
</TabItem>
<TabItem Header="Item 3">
Item 3
</TabItem>
</TabControl>

Resources