WPF Style Triggers TemplateBinding - wpf

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.

Related

General style with specific properties

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.

WPF set ListBoxItem background in trigger

I'm doing a slight modification to code I found on a related stackoverflow post. I made minor changes to a ListBoxItem's background on IsMouseOver and IsSelected using a trigger. In my version I want to use a gradient for the background:
<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="1,2,1,1"/>
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Background" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border Background="{TemplateBinding Background}" />
<Border Background="LightGray" Margin="0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!--<Border Margin="2,1,2,0" Grid.Row="0" Background="#57FFFFFF" />-->
<Border Margin="2,1,2,0" Grid.Row="0">
<Border.Background >
<LinearGradientBrush StartPoint=".5,0" EndPoint="0.5,1" >
<GradientStop Color="White" Offset="0" />
<GradientStop Color="LightGray" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</Border>
<ContentPresenter Margin="0,5" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsSelected" Value="False"/>
</MultiTrigger.Conditions>
<!--<Setter Property="Background" Value="#CCCBAF00" />
<Setter Property="Opacity" Value="0.8" />-->
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint=".5,0" EndPoint="0.5,1" Opacity="0.8">
<GradientStop Color="#CCC9BA5C" Offset="0" />
<GradientStop Color="#CCCBAF00" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="IsSelected" Value="True">
<!--<Setter Property="Background" Value="#CCCB6400" />
<Setter Property="Opacity" Value="0.8" />-->
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint=".5,0" EndPoint="0.5,1" Opacity="0.8">
<GradientStop Color="#CCCD8B4C" Offset="0" />
<GradientStop Color="#CCCB6400" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemContainerStyle" Value="{DynamicResource ListboxItemStyle}" />
<Setter Property="Margin" Value="3,3,2,1" />
</Style>
But it doesn't work with this modification. Thanks!
Just switch
<Border Background="LightGray" Margin="0,0">
to something like
<Border Background="LightGray" Margin="0,0" Opacity="0.5">
to make the ^^ Border see-through
I can see that you have one Border control overlapping another. The first Border (whose Background is bound to template) will never be visible. So, when you change the ListBoxItem's background in trigger, you don't see it because it is hidden below another border.
You can either have just one border control or set the visibility to second border control to hidden in your triggers.

WPF Change color in Xaml based off code behind property

I am trying to change the color of my label based off an enum set in xaml. I can not get the colors to update. Any help would be great.
Thanks!
<UserControl.Resources>
<!-- Normal -->
<SolidColorBrush x:Key="Normal_bg_Unselect" Color="#FF1A73CC" />
<SolidColorBrush x:Key="Normal_fg_Unselect" Color="#FF72BAFF" />
<SolidColorBrush x:Key="Normal_bg_Select" Color="#FF1ACCBF" />
<SolidColorBrush x:Key="Normal_fg_Select" Color="#FF91FFFF" />
</UserControl.Resources>
<Grid>
<Label Name="BackgroundLabel" Width="Auto" Height="Auto" BorderThickness="0" Panel.ZIndex="1" Cursor="Hand">
<Label.Foreground>
<SolidColorBrush Color="{DynamicResource Color_LightBlue}"/>
</Label.Foreground>
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Background" Value="{Binding BgUnselect}" />
<Setter Property="Foreground" Value="{Binding FgUnselect}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding BgSelect}" />
<Setter Property="Foreground" Value="{Binding FgSelect}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="{Binding BgUnselect}" />
<Setter Property="Foreground" Value="{Binding FgUnselect}" />
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
<Label.OpacityMask>
<LinearGradientBrush>
<GradientStop Color="#00FFFFFF" Offset="-.35"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Label.OpacityMask>
</Label>
<TextBlock Name="ContentLabel" Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}, FallbackValue='Styled Button'}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" FontFamily="/HarringtonGroup.TrainingBuilder;component/Fonts/#HelveticaNeue" FontSize="30" Foreground="{Binding ElementName=BackgroundLabel, Path=Foreground}" />
</Grid>
Code Behind
public SolidColorBrush BgUnselect { get; set; }
public SolidColorBrush FgUnselect { get; set; }
public SolidColorBrush BgSelect { get; set; }
public SolidColorBrush FgSelect { get; set; }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
switch (ButtonType)
{
case ButtonType.Normal:
BgUnselect = (SolidColorBrush)FindResource("Normal_bg_Unselect");
FgUnselect = (SolidColorBrush)FindResource("Normal_fg_Unselect");
BgSelect = (SolidColorBrush)FindResource("Normal_bg_Select");
FgSelect = (SolidColorBrush)FindResource("Normal_fg_Select");
return;
case ButtonType.OK:
case ButtonType.Cancel:
return;
}
Your binding tag is incomplete, you must define either RelativeSource or ElementName
Change your UserControl as below
<UserControl x:Name="userControl"
And apply binding as,
Value="{Binding BgSelect, ElementName=userControl}"
By default binding looks for BgSelect as Property of "DataContext" property of User Control.
Also since UserControl is derived from DependencyObject, this will not work unless your property BgSelect etc are dependency properties.
It appears to me, that all you want to do is set the Foreground and Background properties to the resources you defined.
Have you tried replacing your {Binding ...} code with a {StaticResource ...}?
For example, change
<Setter Property="Background" Value="{Binding BgUnselect}" />
to
<Setter Property="Background" Value="{StaticResource Normal_bg_Unselect}" />
EDIT below (based on comment)
You could conceivably use Styles to control the set of 4 colors for each button type. I created a small contrieved example you could apply to your code. If it's not clear, I'll try to rewrite for your code sample.
Create a base style:
<Style x:Key="LabelStyleBase" TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="{DynamicResource ForegroundBrush}"/>
<Setter Property="Background" Value="{DynamicResource BackgroundBrush}"/>
<!-- more style settings -->
</Style>
Then create your variations:
<Style x:Key="LabelStyle1" BasedOn="{StaticResource LabelStyleBase}" TargetType="{x:Type Label}">
<Style.Resources>
<SolidColorBrush x:Key="ForegroundBrush" Color="Purple" />
<SolidColorBrush x:Key="BackgroundBrush" Color="Pink" />
</Style.Resources>
</Style>
<Style x:Key="LabelStyle2" BasedOn="{StaticResource LabelStyleBase}" TargetType="{x:Type Label}">
<Style.Resources>
<SolidColorBrush x:Key="ForegroundBrush" Color="Aqua" />
<SolidColorBrush x:Key="BackgroundBrush" Color="Yellow" />
</Style.Resources>
</Style>
You may get a warning that the resources can't be found, but that should be ok.
Alternate Solution
Finally, if you don't want to go this route, you may have to implement INotifyPropertyChanged on the class and rewrite your setters on the brush properties to fire the NotifyPropertyChanged event.
It's a little unclear how exactly you're implementing the custom Button control, but you should probably have the button type enumeration exposed as a DependencyProperty and change the color brushes on the change notification of the DependencyProperty.
Hope that helps.

WPF ControlTemplate Style GradientStop in Trigger

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>

Is it possible to extend a ControlTemplate the same way you extend a Style in WPF?

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.

Resources