Using the same ControlTemplate in different styles and override a property - wpf

For two TabItems I have two Styles, both use the same ControlTemplate. Now I want styleTabB to show a yellow underline instead of green, but still using the ControlTemplate. How can I modify the Style to accomplish this?
<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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" FontSize="16">
<Window.Resources>
<ControlTemplate x:Key="ctrlTemplate" TargetType="{x:Type TabItem}">
<Grid>
<TextBlock Name="tbTabItemHeaderText"
Text="{TemplateBinding Header}"
Grid.Column="0"
Background="Thistle"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="3,0,0,3">
<TextBlock.TextDecorations>
<TextDecorationCollection>
<TextDecoration Location="Underline"
PenThicknessUnit="Pixel"
PenOffsetUnit="Pixel"
PenOffset="2">
<TextDecoration.Pen>
<Pen Brush="Green" Thickness="4" />
</TextDecoration.Pen>
</TextDecoration>
</TextDecorationCollection>
</TextBlock.TextDecorations>
</TextBlock>
</Grid>
</ControlTemplate>
<!-- Style Tab A -->
<Style x:Key="styleTabA" TargetType="{x:Type TabItem}">
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
<!-- Style Tab B -->
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
</Window.Resources>
<Grid>
<TabControl Name="tabControl">
<TabItem Name="tabItem_1" Header="--- Tab A ---" Style="{StaticResource styleTabA}"/>
<TabItem Name="tabItem_2" Header="--- Tab B ---" Style="{StaticResource styleTabB}" />
</TabControl>
</Grid>
</Window>
UPDATE
I tried the proposal of Chris W., but no underline at all is shown:
<ControlTemplate x:Key="ctrlTemplate" TargetType="{x:Type TabItem}">
...
<TextDecoration.Pen>
<Pen Brush="{TemplateBinding Tag}" Thickness="4" />
</TextDecoration.Pen>
...
</ControlTemplate>
<!--Style Tab A-->
<Style x:Key="styleTabA" TargetType="{x:Type TabItem}">
<Setter Property="Tag" Value="Green" />
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
<!--Style Tab B-->
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Setter Property="Tag" Value="Yellow" />
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>

You can set the style of the children within the child by targetting particular types. Here all Pen are updated with Yellow color.
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Style.Resources>
<Style TargetType="{x:Type Pen}">
<Setter Property="Brush" Value="Yellow"></Setter>
</Style>
</Style.Resources>
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>

#CarbineCoder is correct for most instances but for your instance you're right and the error you received from his would be expected since Pen isn't a TargetType. However if we tweak it just a little to hit the actual FrameworkElement of which TextDecorations is a property let's try this...and read the whole thing since the first snippet is just an example explanation.
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextDecorations">
<Setter.Value>
<TextDecorationCollection>
<TextDecoration>
<TextDecoration.Pen>
<Pen Brush="Yellow"/>
</TextDecoration.Pen>
</TextDecoration>
</TextDecorationCollection>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
** *Except that's not going to work because you're hoping for something that you've already provided an explicit property value for to inherit from parent, and it doesn't work that way. How about instead we bring in the handy Tag property (which I abuse all the time) to piggy back in our value and allow a way to talk to our buddy on the inside of that bugger by making some quick edits to your ControlTemplate like;
<!-- In your STYLE Template you would want to add a default setter of;
<Setter Property="Tag" Value="Green"/>
-->
<ControlTemplate x:Key="ctrlTemplate" TargetType="{x:Type TabItem}">
<Grid Margin="0,0,0,0">
<TextBlock Name="_tbTabItemHeaderText"
Text="{TemplateBinding Header}"
Grid.Column="0"
Background="Thistle"
VerticalAlignment="Center"
Margin="3,0,0,3">
<TextBlock.TextDecorations>
<TextDecorationCollection>
<TextDecoration Location="Underline"
PenThicknessUnit="Pixel"
PenOffsetUnit="Pixel"
PenOffset="2">
<TextDecoration.Pen>
<Pen Brush="{TemplateBinding Tag}" Thickness="4" />
</TextDecoration.Pen>
</TextDecoration>
</TextDecorationCollection>
</TextBlock.TextDecorations>
</TextBlock>
</Grid>
</ControlTemplate>
Now we should be able to hit like;
<!-- Style Tab A
: This guy should just keep it green IF you applied the default setter mentioned above to the STYLE template -->
<Style x:Key="styleTabA" TargetType="{x:Type TabItem}">
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
<!-- Style Tab B
: This guy should turn it Yellow -->
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Setter Property="Tag" Value="Yellow"/>
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
I didn't have time to test, but it seems like this should work fine for your scenario. Hope it helps.

I made a little change on Chris W.'s solution and now it's working:
<ControlTemplate x:Key="ctrlTemplate" TargetType="{x:Type TabItem}">
...
<TextDecoration.Pen>
<!--Changed next line from <Pen Brush="{TemplateBinding Tag}" Thickness="4" /> to:-->
<Pen Brush="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" Thickness="4" />
</TextDecoration.Pen>
...
</ControlTemplate>
<!--Style Tab A-->
<Style x:Key="styleTabA" TargetType="{x:Type TabItem}">
<Setter Property="Tag" Value="Green" />
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>
<!--Style Tab B-->
<Style x:Key="styleTabB" TargetType="{x:Type TabItem}">
<Setter Property="Tag" Value="Yellow" />
<Setter Property="Template" Value="{StaticResource ctrlTemplate}" />
</Style>

Related

Not able to change WPF Toolkit Area Series background

I am using WPF Toolkit Area Chart control. I am not able to change background of the Area Series to any other color. It just assigns color code #FFFFA500.
My XAML code is as below
<chartingToolkit:Chart.Palette x:Uid="tt">
<datavis:ResourceDictionaryCollection>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background" Value="#FF3EA0C0"/>
</Style>
</ResourceDictionary>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background" Value="#FF44C8F5"/>
</Style>
</ResourceDictionary>
</datavis:ResourceDictionaryCollection>
</chartingToolkit:Chart.Palette>
<chartingToolkit:Chart.LegendStyle>
<Style TargetType="Control">
<Setter Property="Width" Value="0"/>
<Setter Property="Height" Value="0"/>
</Style>
</chartingToolkit:Chart.LegendStyle>
<chartingToolkit:AreaSeries Background="Black" x:Name="SecondSeries" DependentValuePath="Value" IndependentValuePath="Key" IsSelectionEnabled="True">
<chartingToolkit:AreaSeries.DataPointStyle>
<Style TargetType="chartingToolkit:AreaDataPoint">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Height" Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:AreaDataPoint">
<Button Name="pointButton" Content="{Binding}" Click="pointButton_Click_1" BorderThickness="1" >
<Button.Template>
<ControlTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Value}" Cursor="Hand"></TextBlock>
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</chartingToolkit:AreaSeries.DataPointStyle>
<chartingToolkit:AreaSeries.DependentRangeAxis>
<chartingToolkit:LinearAxis Orientation="Y" FontFamily="Rockwell" Title="Expenses" FontSize="14" >
</chartingToolkit:LinearAxis>
</chartingToolkit:AreaSeries.DependentRangeAxis>
</chartingToolkit:AreaSeries>
</chartingToolkit:Chart>
Please help me out. This is driving me crazy.
The problem is that there is a Grid within the AreaSeries control Template which has a style applied to it setting the background to a LinearGradientBrush.
In order to change the background of the plot area, add this style
<Style TargetType="Grid" x:Key="plotStyle">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Pink"/>
</Setter.Value>
</Setter>
</Style>
and use it as the Chart control's PlotAreaStyle
<chartingToolkit:Chart Background="Black" PlotAreaStyle="{StaticResource plotStyle}">

How to apply nested Styles from ResourceDictionary in WPF?

I use a DataGrid (WPF 4.0) control. The style for it is placed in a ResourceDictionary and contains a nested Style element:
<Style x:Key="MyDataGridStyle" TargetType="{x:Type controls:DataGrid}">
<Setter Property="Background" Value="Black"/>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Setter.Value>
</Setter>
</Style>
Here, only the Background style is applied. The CellStyle NOT.
It only works when I define the CellStyle directly inside the DataGrid element:
<DataGrid Style="{StaticResource MyDataGridStyle}">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</DataGrid.CellStyle>
</DataGrid>
Any ideas why?
Update
It seems that there is a problem when mixing styles with PresentationFramework.Aero theme that I have referenced in my ResourceDictionary. If I remove the reference it works!
Doing it the way you suggest works fine for me, I'll paste the code that I used to test your style. (note that I added background = red so I could actually see if the style was being applied)
<Window x:Class="WpfApplication1.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="MyDataGridStyle" TargetType="{x:Type DataGrid}">
<Setter Property="Background" Value="Black"/>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Red"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DataGrid Style="{StaticResource MyDataGridStyle}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Text}"/>
<DataGridTextColumn Binding="{Binding Tag}"/>
</DataGrid.Columns>
<DataGrid.Items>
<TextBlock Text="Item1" Tag="aa"/>
<TextBlock Text="Item2" Tag="bb"/>
<TextBlock Text="Item3" Tag="cc"/>
<TextBlock Text="Item4" Tag="dd"/>
</DataGrid.Items>
</DataGrid>
</Window>
the results are

What does a Property Setter correspond to when used in conjunction with ControlTemplates?

I have the following Style (stripped for brevity) and have some questions based on it. To my understanding, if a ControlTemplate replaces the entire visual tree of a control for which the Style is based on, what effect do the property Setters have then?
In this example, don't the property Setters for FontSize, Margin, Height etc. correspond to the respective properties on the CheckBox itself? If you replace the Template property of a control, what will these Setters then correspond to if the CheckBox is no longer rendering it's default appearance?
<Style x:Key="KeyName" TargetType="CheckBox">
<Setter Property="FontSize" Value="11" />
<Setter Property="Margin" Value="0 0 1 0" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Height" Value="18" />
... common property setters etc.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Border>
<StackPanel>
<Ellipse Name="Ellipse" Width="7" Height="7" />
<ContentPresenter Content="{TemplateBinding Content}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.Setters>
<Setter Property="Foreground" Value="WhiteSmoke" />
</Trigger.Setters>
</Trigger>
... custom triggers etc ...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
They are a way to provide an initial default value for properties on the object that's being styled, they don't auto force anything on the Template for you. They can however be used in the control template.
Values that are set using the setters in a style can be overridden by local values in the xaml. for example.
This xaml file draws a single label that has had it's style altered to include a grid that takes on the background color, I've defaulted the color to red in the setter and it appears as red.
<Window x:Class="ContextMenu.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 TargetType="{x:Type Label}">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid Background="{TemplateBinding Background}">
<TextBlock Text="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Label>Test</Label>
</Window>
if I was to change the label line to blue on the instance of the label, you can see this overrides the setter.
<Window x:Class="ContextMenu.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 TargetType="{x:Type Label}">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid Background="{TemplateBinding Background}">
<TextBlock Text="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Label Background="Blue">Test</Label>
</Window>

How to apply style in WPF Controls?

I am beginner on WPF and need your help.
Problem:
I have 4 buttons on the form and need to apply 2 different style on pair of 2 buttons.
Is there any way we can achive this ?
please provide me sample if possible...
Thanks in advance...
You can define named styles and then assign them explicitly to any controls as you wish.
Here is a primer for styling buttons: Getting Started with WPF : Button Control Part 2 – Basic Styling
And here is an example:
<Window x:Class="WpfButtonStyling.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="400">
<Window.Resources>
<Style x:Key="ButtonStyle1"
TargetType="{x:Type Button}">
<Setter Property="Foreground"
Value="Red" />
<Setter Property="Margin"
Value="10" />
</Style>
<Style x:Key="ButtonStyle2"
TargetType="{x:Type Button}">
<Setter Property="Foreground"
Value="Blue" />
<Setter Property="Margin"
Value="10" />
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button x:Name="FirstButton"
Content="First!"
Style="{StaticResource ButtonStyle1}"/>
<Button x:Name="SecondButton"
Content="Second"
Style="{StaticResource ButtonStyle2}" />
</StackPanel>
</Grid>
</Window>
If someone want to write Style directly in Button, write like below:
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="TimesNewRoman" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Button.Style>
</Button>
Use this Code For different styles for different buttons or any other
<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"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Window.Resources>
**<Style x:Key="a" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Indigo"/>
</Style>
<Style x:Key="b" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="16"/>
</Style>
<Style x:Key="c" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="TimesNewRoman" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<TextBlock Margin="26,41,39,0" Style="{StaticResource a}" Height="100" VerticalAlignment="Top">TextBlock with Style1</TextBlock>
<TextBlock Margin="26,77,39,0" Height="32" VerticalAlignment="Top">TextBlock with no Style</TextBlock>
<TextBlock Margin="26,105,67,96" Style="{StaticResource b}">TextBlock with Style2</TextBlock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="26,170,-26,0">
<Button Style="{StaticResource c}">
<Bold >Styles</Bold></Button>
<Button Style="{StaticResource c}">are</Button>
<Button Style="{StaticResource c}">cool</Button>
</StackPanel>
</Grid>
here i declaring the style for both textBlock and button.Use this one..

WPF UserControl Style

I want to set the background property of all the usercontrols of my project.
I tried with
<style TargetType={x:Type UserControl}>
<setter property="Background" Value="Red" />
</style>
It compiles but didn't work.
¿Any Idea?
Thanks!
You can only set a a style to a specific class, so this will work (create a UserControl object, not very useful):
<Window.Resources>
<Style TargetType="{x:Type UserControl}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<UserControl Name="control" Content="content"></UserControl>
</Grid>
But this doesn't (Create a class derived from UserControl):
<Window.Resources>
<Style TargetType="{x:Type UserControl}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<l:MyUserControl Name="control" Content="content"></l:MyUserControl>
</Grid>
What you can do is either explicitly set the style using the Style property:
<Window.Resources>
<Style TargetType="{x:Type UserControl}" x:Key="UCStyle">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<l:MyUserControl Name="control" Content="content" Style="{StaticResource UCStyle}"></l:MyUserControl>
</Grid>
or create a style for each derived class, you can use BasedOn to avoid duplicating the style content:
<Window.Resources>
<Style TargetType="{x:Type UserControl}" x:Key="UCStyle">
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="{x:Type l:MyUserControl}" BasedOn="{StaticResource UCStyle}" />
</Window.Resources>
<Grid>
<l:MyUserControl Name="control" Content="content"></l:MyUserControl>
</Grid>
I think you're missing some double quotes:
Try this:
<Window.Resources>
<Style TargetType="{x:Type UserControl}">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<UserControl Name="control" Content="content"></UserControl>
</Grid>

Resources