I would like to have a dynamic ToolTip style that changes the foreground color based on the text of different string properties (in this code example, the string is PosError, but it could be any property name, and if the value is "Error", the DataTrigger is triggered.
As for now, I have to do it like this for each and every TextBox: Change the property binding of the DataTrigger and the text of the ToolTip (in this example, the string property is PosExtreme):
<TextBox
Width="150"
FontSize="25"
MaxWidth="150"
Name="posTab"
TextAlignment="Center"
Text="{Binding PosTabStrength, UpdateSourceTrigger=PropertyChanged}">
<TextBox.ToolTip>
<ToolTip>
<ToolTip.Style>
<Style TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding PosError}" Value="Error">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolTip.Style>
<TextBlock Text="{Binding PosExtreme}"/>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
I would like to have the ToolTip style as ResourceDictionary file and not having to copy and paste the code and modify it for every TextBox with it's proper ToolTip style and ToolTip text.
Is this possible?
Your main blocker for reusing the style are the bindings to concrete properties and the hard-coded Error string. You need to pass them from outside of the style and control template.
Your comparison of the DataTrigger can be encapsulated in a value converter that returns a boolean for the comparison of any bound property (PosError) with a fixed value (Error) passed as parameter.
public class ErrorComparisonToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null && parameter != null && value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
In the DataTrigger, we do not bind a concrete property anymore, but the Tag of the ToolTip, which is a general purpose property.
Gets or sets an arbitrary object value that can be used to store custom information about this element.
We assume that the comparison is done for us already and the Tag only contains the result true or false. This simplifies the DataTrigger and the dependency on PosError is gone.
Next, you can eliminate the TextBlock inside the ToolTip. ToolTip is a ContentControl and exposes a Content property. This content is shown automatically using the ContentPresenter inside the ControlTemplate. The dependency on PosExtreme is gone, too.
Move the style out in a resource dictionary in scope and create an instance of the converter, too.
<local:ErrorComparisonToBoolConverter x:Key="ErrorComparisonToBoolConverter"/>
<Style x:Key="MyToolTipStyle" TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can reuse the style now and bind PosExtreme or any other property to the Content of ToolTip and the error property to Tag. The Tag binding uses the value converter to compare the bound value to the expected error code passed as CommandParameter.
<TextBox.ToolTip>
<ToolTip Style="{StaticResource MyToolTipStyle}"
Content="{Binding PosExtreme}"
Tag="{Binding PosError, ConverterParameter=Error, Converter={StaticResource ErrorComparisonToBoolConverter}}">
</ToolTip>
</TextBox.ToolTip>
Remarks
The solution uses the Tag property to propagate the error property. In your example it works, but if you need to bind even more properties in the style or control template, you would have to create attached properties for each that you can bind instead of Tag. For a single property, Tag is just convenient.
You could also create a custom ToolTip control that exposes dependency properties for the properties used in the style and control template instead of attached properties and do the comparison within.
Depending on how your data items are implemented, you could eliminate the converter completely, by exposing a bool property, if that makes sense.
Related
I tried to set up a custom styled treeview that does "just in time" loading by two-way binding the expanded property to a similar property in the view-model. The style and functionality aspects work fine on their own, but not when put together.
When I do it like this the functionality is there:
<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
<TreeView.Resources>
<ResourceDictionary Source="GroupedTreeViewItemStyle.xaml"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
But when I add the BasedOn to use my custom style it does no longer load any nodes.
I use my style by replacing the above style definition with the following:
<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">
And here is my custom style based on this tutorial:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="*******namespace omitted*******">
<!-- This Style redefines the ControlTemplate used by TreeViewItems and
also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
<Style.Resources>
<LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<DropShadowBitmapEffect x:Key="DropShadowEffect" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Margin="8,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- This Border contains elements which display
the content and child items of the TreeViewItem. -->
<Border Name="Bd"
Background="{StaticResource ItemAreaBrush}"
BorderBrush="{StaticResource ItemBorderBrush}"
BorderThickness="0.6"
CornerRadius="8"
Padding="6"
SnapsToDevicePixels="True"
>
<Grid>
<!-- Items with children are
shown in an Expander. -->
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
<Expander.Header>
<!-- Displays the item's header in the Expander. -->
<ContentPresenter ContentSource="Header" />
</Expander.Header>
<!-- Displays the item's children. -->
<ItemsPresenter />
</Expander>
<!-- Items without children are
shown in a ContentPresenter. -->
<ContentPresenter Name="CntPres"
ContentSource="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<!-- If the TreeViewItem has child items,
show it in an Expander. Otherwise
hide the Expander and show the hidden
ContentPresenter. -->
<Trigger Property="TreeViewItem.HasItems" Value="false">
<Setter
TargetName="Exp"
Property="Visibility"
Value="Collapsed" />
<Setter
TargetName="CntPres"
Property="Visibility"
Value="Visible" />
</Trigger>
<!--When the item is selected in the TreeView, use the
"selected" colors and give it a drop shadow. -->
<Trigger Property="IsSelected" Value="true">
<Setter
TargetName="Bd"
Property="Panel.Background"
Value="{StaticResource SelectedItemAreaBrush}" />
<Setter
TargetName="Bd"
Property="Border.BorderBrush"
Value="{StaticResource SelectedItemBorderBrush}" />
<!--<Setter
TargetName="Bd"
Property="TextElement.Foreground"
Value="{DynamicResource
{x:Static SystemColors.HighlightTextBrushKey}}" />-->
<Setter
TargetName="Bd"
Property="Border.BitmapEffect"
Value="{StaticResource DropShadowEffect}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Make each TreeViewItem show it's children
in a StackPanel. If it is a root item then
the Orientation will be 'Horizontal', else
'Vertical'. -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsPanelTemplate.Resources>
<this:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel
IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Does anybody know, what I am doing wrong in combining the style and functionality of my tree?
Is the problem that the style already defines something according to the isExpanded property? Or is there something missing, something along the lines of super(isExpanded)?
Thanks for your help!
Expander binding is probably the cause of the issue:
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
according to documentation,
A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.
(see also TemplateBinding limitations)
try re-write binding as:
<Expander Name="Exp"
IsExpanded="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}">
I'm new to WPF and I am struggling to find the solution to what I'm trying to do as I'm still a little uncertain as to whether I'm doing this correctly.
I have the following style defined for a button
<Style x:Key="ToolBarButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Margin" Value="5" />
<Setter Property="BorderBrush" Value="White" />
<Setter Property="Background" Value="{DynamicResource CompanyBlue}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Width" Value="100" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonBorder" BorderThickness="5" CornerRadius="5"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}">
<ContentPresenter Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,-0.2" EndPoint="0,1.2">
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="{ORIGINAL-COLOR}" Offset="0.5" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
In the XAML, where I have put the placeholder {ORIGINAL-COLOR}, I essentially want this to be the value that is used previously set with {TemplateBinding Background} for the control template of the style.
I've seen suggestions that I should use {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background} but this is not working.
Thanks in advance for any help.
I believe the problem is that LinearGradientBrush is not a FrameworkElement and doesn't belong to layout tree. Only FrameworkElements have DataContext property and in consequence can make use of bindings. What you're trying to do is to set up a Binding on GradientStop.
Your trigger should look like this:
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Background"
Value="{TemplateBinding Background, Converter={StaticResource myConverter}}">
</Setter>
</Trigger>
And myConverter is a custom converter class that will take value of Background and return a complete LinearGradientBrush instance created from input brush. I'll assume you know how to write converters. Remember it needs to be added to resources.
More or less something like this:
class BrushToGradient : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var brush = (Brush)value;
var gradient = new LinearGradientBrush();
//Make it manually
gradient.GradientStops.Add(...);
//...
return gradient;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can't bind Color with Background property since return type of Background is Brush and not Color.
Bind with Color property of Brush. Since background is binded to resource CompanyBlue so use that binding in your trigger as well -
<GradientStop Color="{Binding Color, Source={StaticResource CompanyBlue}}"
Offset="0.5" />
Try it like this
<GradientStop Color="White" Offset="0" />
<GradientStop Color="{DynamicResource CompanyBlue}" Offset="0.5" />
<GradientStop Color="White" Offset="1" />
I hope this will help.
I want to set header of datagrid like following link.
Style in HeaderColumn in Datagrid
I have used DataGridColumnHeadersPresenter in my code.
See my following code:
<Style x:Key="XYZ" TargetType="sdk:DataGridColumnHeadersPresenter" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridRowGroupHeader">
<Border x:Name="ButtonBorder"
CornerRadius="0,0,0,0"
BorderThickness="0"
BorderBrush="Transparent">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#555" Offset="0.0"/>
<GradientStop Color="#000" Offset="0.8"/>
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ItemsPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="BreakGridStyle" TargetType="sdk:Datagird">
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGrid">
<Grid>
<StackPanel>
<sdk:DataGridColumnHeadersPresenter Name="ABC" Style="{StaticResource XYZ}" />
<ItemsPresenter/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But i got following Error:
The property 'Template' was not found in type 'System.Windows.Controls.Primitives.DataGridColumnHeadersPresenter'.
How to solve this and how to achieve my datagrid's column style as in above link
Here is my XAML for a TabItem. I want to be able to set the Color of a single gradient stop in a trigger. I know that I can re-define the gradient completely in the trigger's setter, but I want to access a specific property on the background so I can animate it in the future.
I have tried every variation of everything in the trigger's setter and googled for a long time - but I still can't get it to compile. I have also tried class.property syntax, but still nothing. The current error this code raises is:
"Type 'Background.GradientStops[0]' was not found."
I am pretty sure I know what is going on here - and perhaps what I want is impossible. But there has to be a way to animate a control's gradient in a control template...
Can anyone help me?
thanks
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<TextBlock Padding="6 2 6 2" Name="TheHeader">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0, 0" EndPoint="0, 1">
<GradientStop Offset="0" Color="#f4fafd" />
<GradientStop Offset="1" Color="#ceedfa" />
</LinearGradientBrush>
</TextBlock.Background>
<ContentPresenter ContentSource="Header" Margin="0" />
</TextBlock>
<ControlTemplate.Triggers >
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="TheHeader" Property="Background.GradientStops[0].Color" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can animate it, like in the example here.
You also could use a slight hack to set it, though I always prefer creating multiple brushes as resources and swapping them or re-creating a brush in the as you mentioned.
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<TextBlock Padding="6 2 6 2"
Name="TheHeader" Tag="#f4fafd">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0, 0"
EndPoint="0, 1">
<GradientStop Offset="0"
Color="{Binding ElementName=TheHeader, Path=Tag}"/>
<GradientStop Offset="1"
Color="#ceedfa" />
</LinearGradientBrush>
</TextBlock.Background>
<ContentPresenter ContentSource="Header"
Margin="0" />
</TextBlock>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter TargetName="TheHeader"
Property="Tag"
Value="Red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So the thing is that I have a main ControlTemplate which defines the most basic stuff for the new button look we're designing. But I want to do 3 other control templates for this button so we can set different colors in those; but I don't want to copy paste the main ControlTemplate and change the color there, instead I want to "inherit" from that (like with the BasedOn property in Style) and change the color in the inherited ControlTemplate.
Is this possible?
Thanks!
Found the solution. You don't extend ControlTemplates, instead you define all the basic behavior you want, and then you let either a style or the control itself modify it. Take the example below for instance. The ControlTemplate sets the OpacityMask and the round corners for my rectangle, the Styles sets the color of the background for each button (with help of a TemplateBinding), and there's my solution:
<Window.Resources>
<ControlTemplate x:Key="BaseMainButtonTemplate" TargetType="{x:Type Button}">
<Grid TextBlock.Foreground="White" TextBlock.FontFamily="Calibri">
<Rectangle Stroke="#FFE8E6E6" x:Name="rectangle" RadiusX="14.5" RadiusY="14.5" Fill="{TemplateBinding Property=Background}"> <!-- This TemplateBinding takes the color set by the style and applies it to the rectangle. Doing it this way, allows the style to modify the background color -->
<Rectangle.OpacityMask>
<LinearGradientBrush EndPoint="0,1" SpreadMethod="Reflect">
<GradientStop Offset="0" Color="Transparent"></GradientStop>
<GradientStop Offset="1" Color="Gray"></GradientStop>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<!-- OpacityMask when it's Focused, Defaulted and Mouse is over -->
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="OpacityMask" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" SpreadMethod="Repeat">
<GradientStop Offset="1" Color="Transparent"></GradientStop>
<GradientStop Offset="0" Color="Gray"></GradientStop>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<!-- OpacityMask when it's pressed -->
<Trigger Property="IsPressed" Value="True">
<Setter Property="Stroke" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF223472" Offset="0"/>
<GradientStop Color="#FFF2F0F0" Offset="0.911"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="StrokeThickness" TargetName="rectangle" Value="3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="BlueButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Blue" />
<Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
</Setter>
</Style>
<Style x:Key="RedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
<Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
</Setter>
</Style>
<Style x:Key="GreenButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
<Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel>
<Button Style="{StaticResource BlueButtonStyle}" Height="30" Content="Test">
</Button>
<Button Style="{StaticResource RedButtonStyle}" Height="30" Content="Test">
</Button>
<Button Style="{StaticResource GreenButtonStyle}" Height="30" Content="Test">
</Button>
</StackPanel>
</Grid>
Alternately you can define a "DynamicResource" reference to any dependency property in your Control Template and have it go resolve it's value given the presence of available resources.
For example, you can set Background="{DynamicResource SomeBrushColorVariable}"
Then SomeBrushColorVariable can change given different ResourceDictionaries that are merged into your App.xaml file or even set by the user given some user preferences display setting or color scheme.