override control template property in XAML - wpf

If I have the following XAML defined in generic.xaml
<Style TargetType="{x:Type TextBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="CaretBrush" Value="{StaticResource TextBoxCaretBrush}" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="MinWidth" Value="120" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="AllowDrop" Value="True" />
<Setter Property="Foreground" Value="{StaticResource TextBoxTextBrush}" />
<Setter Property="Padding" Value="5,3,0,5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border x:Name="Border" CornerRadius="5" Padding="2" BorderThickness="1">
<Border.Background>
<SolidColorBrush Color="{StaticResource TextBoxBackgroundColor}" />
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="{StaticResource TextBoxBorderColor}" />
</Border.BorderBrush>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" TargetName="Border" Value="{StaticResource TextBoxBorderSelectedBrush}" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="{StaticResource HighlightColor}" Opacity="1" BlurRadius="5" />
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And in my view I have defined the following XAML to display a TextBox using the above style.
<TextBox Name="UserName" attachedProperties:KeyboardNavigationExt.TabOnEnter="True" Grid.Row="1" KeyboardNavigation.TabIndex="1" Grid.Column="2" Grid.ColumnSpan="3" cal:Message.Attach="[Event TextChanged] = [Action CanLogin]" />
This display a TextBox on the view with a CornerRadius of 5 on the Border in the Template.
Now for my question, I have a scenario where there are two TextBox adjacent to each other and I would like to specify the CornerRadius for both TextBox something like the below.
<TextBox Name="UserName" CornerRadius="5,5,0,0" attachedProperties:KeyboardNavigationExt.TabOnEnter="True" Grid.Row="1" KeyboardNavigation.TabIndex="1" Grid.Column="2" Grid.ColumnSpan="3" cal:Message.Attach="[Event TextChanged] = [Action CanLogin]" />
But TextBox does not have a CornerRadius how can I achieve this so that I am able to change the CornerRadius of the Border in the view XAML

As mentioned in the comment you need proxy property that you can set against TextBox and bind in template. So create AttachedProprty of CornerRadius type
public static class AttachedProperties
{
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius), typeof(AttachedProperties), new UIPropertyMetadata());
public static void SetCornerRadius(DependencyObject d, CornerRadius source)
{
d.SetValue(CornerRadiusProperty, source);
}
public static CornerRadius GetCornerRadius(DependencyObject d)
{
return (CornerRadius)d.GetValue(CornerRadiusProperty);
}
}
change ControlTemplate and bind to that property of TemplatedParent
<ControlTemplate TargetType="{x:Type TextBox}">
<Border CornerRadius="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:AttachedProperties.CornerRadius)}"/>
</ControlTemplate>
addSetter to your Style with default value
<Setter Property="local:AttachedProperties.CornerRadius" Value="5"/>
and then you can change it manually against each TextBox
<TextBox local:AttachedProperties.CornerRadius="5,5,0,0" .../>

Related

Changing Combobox/Table Item textcolor on Mouseover in ResourceDictionary

I am using MahAppsMetro and therefore I have a ResourceDictionary where I can change the color of the design.
Now I changed the color to blue. But I do not know how to change the textcolor of an selected item in an combobox / table.
It looks like this now:
Example: Combobox
Example: Table
So now I want to change the Textcolor to white by the ResourceDictionary..
It looks something like this yet:
<!-- re-set brushes too -->
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush2" Color="{StaticResource AccentColor2}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush3" Color="{StaticResource AccentColor3}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush4" Color="{StaticResource AccentColor4}" options:Freeze="True" />
<SolidColorBrush x:Key="WindowTitleColorBrush" Color="{StaticResource AccentColor}" options:Freeze="True" />
<LinearGradientBrush x:Key="ProgressBrush" EndPoint="0.001,0.5" StartPoint="1.002,0.5" options:Freeze="True">
<GradientStop Color="{StaticResource HighlightColor}" Offset="0" />
<GradientStop Color="{StaticResource AccentColor3}" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="CheckmarkFill" Color="{StaticResource AccentColor}" options:Freeze="True" />
<SolidColorBrush x:Key="RightArrowFill" Color="{StaticResource AccentColor}" options:Freeze="True" />
Can you tell me what I need to add to my ResourceDictionary to have a white text on MouseOver of the items.
Hope it is clear what I want to do. Else please tell me what further information you need.
edit:
For the Combobox is it working now. But not for the DataGrid.
Here is how I added the DataGrid:
<DataGrid x:Name="mydatagrid" SelectionUnit="FullRow" HorizontalAlignment="Left" Margin="159,33,0,0" VerticalAlignment="Top" Height="204" Width="275" Background="{x:Null}" BorderBrush="Transparent" CanUserAddRows="False" GridLinesVisibility="None" BorderThickness="0" CanUserResizeRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="User" Binding="{Binding User, Mode=OneWay}" Width="100" IsReadOnly="True" CanUserResize="False" />
<DataGridTextColumn Header="Vote" Binding="{Binding Vote, Mode=OneWay}" Width="90" IsReadOnly="True" CanUserResize="False" />
<DataGridTemplateColumn Header="Status" Width="66" IsReadOnly="True" CanUserResize="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Status, Mode=OneWay}" Width="16"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Real_Username" Binding="{Binding Real_Username, Mode=OneWay}" Width="90" IsReadOnly="True" CanUserResize="False"/>
</DataGrid.Columns>
</DataGrid>
I tried to add different methods to my Application.xaml and expanded the triggers of IsMouseOver with:
<Setter Property="Controls.Foreground" Value="{DynamicResource AccentSelectedColorBrush}" />
What am I doing wrong?
it is possible, but for the MouseOver you need to override MahApps ComboBoxItem and extend it with a Trigger. The SelectedItem uses the ColorBrush: AccentSelectedColorBrush.
Here is the original MetroComboBoxItem extended with a Trigger for MouseOver
app.xaml
<Application x:Class="WpfApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="AccentSelectedColorBrush" Color="DeepPink" />
<Style TargetType="ComboBoxItem" x:Key="MetroComboBoxItem">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="Padding" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="{DynamicResource TransparentWhiteBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid Background="{TemplateBinding Background}" Margin="0,0.5">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="MouseOverRectangle">
<EasingDoubleKeyFrame KeyTime="0:0:0.1"
Value=".65" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="contentPresenter">
<SplineDoubleKeyFrame KeyTime="0"
Value=".55" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="SelectedRectangle">
<EasingDoubleKeyFrame KeyTime="0:0:0.1"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard />
</VisualState>
<VisualState x:Name="Unfocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="SelectedRectangle"
IsHitTestVisible="False"
Opacity="0"
Fill="{DynamicResource AccentColorBrush}" />
<Rectangle x:Name="MouseOverRectangle"
IsHitTestVisible="False"
Opacity="0"
Fill="{DynamicResource AccentColorBrush3}" />
<ContentControl Foreground="{TemplateBinding Foreground}">
<ContentPresenter x:Name="contentPresenter"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</ContentControl>
<Rectangle x:Name="FocusVisualElement"
Stroke="{DynamicResource HighlightBrush}"
StrokeThickness="1"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{DynamicResource AccentSelectedColorBrush}" />
</Trigger>
<!-- This Trigger is new -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource AccentSelectedColorBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
For DataGrid it is easy:
if you like to style whole Line cells, OnMouseOver or IsSelected use this:
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Foreground" Value="Green" />
<Style.Triggers>
<!-- Full Row -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=IsMouseOver}" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Opacity" Value="0.8" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridRow}, Path=IsSelected}" Value="True">
<Setter Property="Foreground" Value="DeepPink" />
<Setter Property="Opacity" Value="0.3" />
</DataTrigger>
</Style.Triggers>
</Style>
Cells only this:
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Foreground" Value="Green" />
<Style.Triggers>
<!-- Cell only -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Opacity" Value="0.8" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True">
<Setter Property="Foreground" Value="DeepPink" />
<Setter Property="Opacity" Value="0.3" />
</DataTrigger>
</Style.Triggers>
</Style>
You can place the Style in your app.xaml to work for your whole application.

I Don't want message "SELECT DATE" in DatePicker

I don't want display "Select Date" in textbox of DatePicker but I want see something like this //____ or another text.
This is my RESOURCE
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ABC" TargetType="DatePicker">
<Setter Property="Foreground" Value="#FF333333" />
<Setter Property="IsTodayHighlighted" Value="True" />
<Setter Property="SelectedDateFormat" Value="Short" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="DisplayDateStart" Value=" 01/01/1990" />
<Setter Property="DisplayDateEnd" Value="12/31/2090" />
<Setter Property="Padding" Value="2"/>
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value ="Center" />
<Setter Property="VerticalAlignment" Value= "Center" />
<Setter Property = "Text" Value="{x:Null}" />
<Setter Property = "SelectedDate" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Background" Value="Coral"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property= "Background" Value="LemonChiffon"/>
</Trigger>
</Style.Triggers>
</Style>
You can modify the default template for the DatePickerTextBox
The thing to change is the 'PART_Watermark' ContentControl. The code for the DatePicker sets the Content property of this control, so we can't just change the Content. Instead override the ControlTemplate for this control and just make it a TextBlock with the text you want.
<ContentControl x:Name="PART_Watermark"
Opacity="0"
Focusable="False"
IsHitTestVisible="False"
Padding="2">
<ContentControl.Template>
<ControlTemplate>
<TextBlock Text="//____"/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
Here's the whole thing:
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DatePickerTextBox">
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="WatermarkBrush" Color="#FFAAAAAA"/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
<VisualTransition To="MouseOver" GeneratedDuration="0:0:0.1" />
</VisualStateGroup.Transitions>
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" To="#FF99C1E2" Duration="0"/>
<ColorAnimation Storyboard.TargetName="watermark_decorator" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" To="#FF99C1E2" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="WatermarkStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState Name="Unwatermarked" />
<VisualState Name="Watermarked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Opacity" To="0" Duration="0" />
<DoubleAnimation Storyboard.TargetName="PART_Watermark" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="FocusStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState Name="Unfocused" />
<VisualState Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
CornerRadius="1"
Opacity="1">
<Grid x:Name="WatermarkContent"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Border x:Name="ContentElement" BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="#FFFFFFFF"/>
</Border.BorderBrush>
</Border>
<Border x:Name="watermark_decorator" BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="#FFFFFFFF"/>
</Border.BorderBrush>
<ContentControl x:Name="PART_Watermark"
Opacity="0"
Focusable="False"
IsHitTestVisible="False"
Padding="2">
<ContentControl.Template>
<ControlTemplate>
<TextBlock Text="//____"/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
</Border>
<ScrollViewer x:Name="PART_ContentHost"
Margin="0"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
<Border x:Name="FocusVisual" BorderBrush="#FF45D6FA" CornerRadius="1" Opacity="0" IsHitTestVisible="False"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Extending #wizzardz's answer, you may introduce a DependencyProperty in Code to set the value in XAML on DesingTime:
public class CustomDatePicker : DatePicker
{
public string WatermarkText
{
get { return (string)GetValue(WatermarkTextProperty); }
set { SetValue(WatermarkTextProperty, value); }
}
public static readonly DependencyProperty WatermarkTextProperty =
DependencyProperty.Register("WatermarkText", typeof(string), typeof(CustomDatePicker), new PropertyMetadata("Datum wählen..."));
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
DatePickerTextBox box = base.GetTemplateChild("PART_TextBox") as DatePickerTextBox;
box.ApplyTemplate();
ContentControl watermark = box.Template.FindName("PART_Watermark", box) as ContentControl;
watermark.Content = WatermarkText;
}
}
and in XAML
<local:CustomDatePicker WatermarkText="Start"/>
This way you may also set Binding on the Watermarktext.
This is another solution from the code
public class CustomWatermarkedDatePicker : DatePicker
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
DatePickerTextBox box = base.GetTemplateChild("PART_TextBox") as DatePickerTextBox;
box.ApplyTemplate();
ContentControl watermark = box.Template.FindName("PART_Watermark", box) as ContentControl;
watermark.Content = "Custom Text";
}
}
Hope this helps.

ControlTemplate with VisualState ColorAnimation binding to attached property

I have an attached property that I would like to bind to in my button's ControlTemplate VisualStateManager.
Below is the code for the property and the XAML for the button style. I have no errors or warnings, but the button doesn't change colors when I mouse over it or when I press it.
What's wrong with this? I've looked at the following examples and they haven't worked so far:
How to use Attached property within a style?
Problem reading AttachedProperty in ControlTemplate
Here's the property:
using System.Windows;
using System.Windows.Media;
namespace company.project.Utilities.AttachedBehaviors
{
public class Attached : DependencyObject
{
// Attached properties...
#region MouseOverColor Property
public static readonly DependencyProperty MouseOverColorProperty = DependencyProperty.RegisterAttached(
"MouseOverColor",
typeof(Color),
typeof(Attached)
);
public static void SetMouseOverColor(UIElement element, Color value)
{
element.SetValue(MouseOverColorProperty, value);
}
public static Color GetMouseOverColor(UIElement element)
{
return (Color)element.GetValue(MouseOverColorProperty);
}
#endregion
#region PressedColor Property
public static readonly DependencyProperty PressedColorProperty = DependencyProperty.RegisterAttached(
"PressedColor",
typeof(Color),
typeof(Attached)
);
public static void SetPressedColor(UIElement element, Color value)
{
element.SetValue(PressedColorProperty, value);
}
public static Color GetPressedColor(UIElement element)
{
return (Color)element.GetValue(PressedColorProperty);
}
#endregion
}
}
Here's the style:
xmlns:attached="clr-namespace:company.project.Utilities.AttachedBehaviors;assembly=company.project.Utilities"
<Style x:Key="DialogButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource StandardButtonStyle}">
<Setter Property="Background" Value="{StaticResource ElectroTekGrayBrush}" />
<Setter Property="attached:Attached.MouseOverColor" Value="{StaticResource ElectroTekGreen}" />
<Setter Property="attached:Attached.PressedColor" Value="{StaticResource ElectroTekLightGray}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="{Binding Path=(attached:Attached.MouseOverColor), RelativeSource={RelativeSource AncestorType=Button}}" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="{Binding Path=(attached:Attached.PressedColor), RelativeSource={RelativeSource AncestorType=Button}}" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Name="Border" Background="{TemplateBinding Background}" CornerRadius="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource MathConverter}, ConverterParameter=(#VALUE/2)}" IsHitTestVisible="True">
<Grid>
<TextBlock x:Name="TextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="15" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="TextBlock" Property="Cursor" Value="Hand" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here's the button:
<Button Style="{StaticResource DialogButton}" />
Alright, I assumed that #King King was correct about the To and From properties and just implemented the same functionality using triggers. Here's the style if anybody needs it.
<Style x:Key="DialogButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource StandardButtonStyle}">
<Setter Property="Background" Value="{StaticResource ElectroTekGrayBrush}" />
<Setter Property="attached:Attached.MouseOverColor" Value="{StaticResource ElectroTekGreen}" />
<Setter Property="attached:Attached.PressedColor" Value="{StaticResource ElectroTekOrange}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border Name="border" Background="{TemplateBinding Background}" CornerRadius="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource MathConverter}, ConverterParameter=(#VALUE/2)}" IsHitTestVisible="True" Cursor="Hand">
<TextBlock x:Name="TextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="15" Cursor="Hand" />
</Border>
</Grid>
<ControlTemplate.Resources>
<SolidColorBrush x:Key="MouseOverBrush" Color="{Binding Path=(attached:Attached.MouseOverColor), RelativeSource={RelativeSource AncestorType=Button}}" />
<SolidColorBrush x:Key="PressedBrush" Color="{Binding Path=(attached:Attached.PressedColor), RelativeSource={RelativeSource AncestorType=Button}}" />
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="border">
<Setter Property="Background" Value="{StaticResource MouseOverBrush}" TargetName="border" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource PressedBrush}" TargetName="border" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF, Create brush animation in Style.Triggers of a button style

I am working now on a Button style, I've included a control template and style triggers. Now I want to make the background brush fade to a certain colour when mouse enter to button. But the colour animation won't work with a brush. and I'm stuck on that since yesterday. Here is what I've done so far in my button style:
<Converters:MathConverter x:Key="MathConverter" />
<Converters:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<Style TargetType="Button">
<Setter Property="FontSize"
Value="{Binding FontSizeButton}" />
<Setter Property="Margin"
Value="{Binding FontSizeBase, Converter={StaticResource MathConverter}, ConverterParameter=#VALUE/3}" />
<Setter Property="Padding"
Value="{Binding FontSizeButton, Converter={StaticResource MathConverter}, ConverterParameter=#VALUE/3}" />
<Setter Property="MinWidth"
Value="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" />
<Setter Property="Width"
Value="NaN" />
<Setter Property="Background"
Value="{Binding BrushBackButton}" />
<Setter Property="BorderBrush"
Value="{Binding BrushBorder}" />
<Setter Property="BorderThickness"
Value="{Binding BorderThicknessBase}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="MainBorder" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<ContentPresenter x:Name="Content"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!--
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{Binding BrushBackButtonOver}" />
</Trigger>
-->
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Background">
<ColorAnimation To="Blue" Duration="10"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
You should use the VisualStateManager for this kind of problem.
It may lead you to something like that :
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name ="Border" Background="LightBlue">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
To="Red"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
To="Blue"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
[...]
[Edit]
Concerning your specific problem, you should put your trigger in the ControlTemplate's Triggers.
<ControlTemplate TargetType="{x:Type Button}">
[...]
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard TargetName="Border" TargetProperty="(Background).(SolidColorBrush.Color)">
<ColorAnimation To="Blue" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>

ColorAnimationUsingKeyFrames changes brush

Well hi, I am kind of new to WPF and this is the first time I tried change styles of WPF controls. Thanks to Expression Blend everything went better than expected until I made this style.
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PART_ContentHost">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Background">
<EasingColorKeyFrame KeyTime="0" Value="Red"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)" Storyboard.TargetName="Background">
<EasingColorKeyFrame KeyTime="0" Value="Yellow"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly"/>
<VisualState x:Name="MouseOver"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Background" Fill="{StaticResource ControlBackgroundBrush}" Stroke="{StaticResource NormalBrush}" RadiusX="2" RadiusY="2"/>
<ScrollViewer x:Name="PART_ContentHost" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" FontFamily="{TemplateBinding FontFamily}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
Those two brushes are here:
<Color x:Key="MainColor">#FF595959</Color>
<Color x:Key="ControlBackgroundColor">#FF333333</Color>
<SolidColorBrush x:Key="NormalBrush" Color="{DynamicResource MainColor}"/>
<SolidColorBrush x:Key="ControlBackgroundBrush" Color="{StaticResource ControlBackgroundColor}" />
Well and what is the problem. Disabling TextBox should change BorderColor and Background of TextBox but it also changes color of everything what uses NormalBrush. I want to have just few brushes common for all controls to let the theme be easily modified. One more thing I use them Usualy in other styles as StaticResource. Your suggestions and help would be highly appreciated.
StaticResource is by definition STATIC (Shared), so animating a property of a STATIC resource will affect ALL elements that use the StaticResource within its scope. By marking the x:Shared attribute to FALSE, WPF will create an instance for each element that uses it versus one static resource:
<SolidColorBrush x:Key="OniiNormalBrush" x:Shared="False" Color="{StaticResource MainColor}"/>
Well I never found out why one color is changed everywhere and the second one is not. As suggested in comments I changed that style to use triggers instead of visualStates and everything works fine.
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Rectangle x:Name="Background" Fill="{StaticResource ControlBackgroundBrush}" Stroke="{StaticResource NormalBrush}" RadiusX="2" RadiusY="2"/>
<ScrollViewer x:Name="PART_ContentHost" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" FontFamily="{TemplateBinding FontFamily}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Fill" TargetName="Background" Value="Red" />
<Setter Property="Stroke" TargetName="Background" Value="Green" />
<Setter Property="Foreground" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
EDIT
Everything was coused by definition of NormalBrush where Color was DynamicResource

Resources