The default behavior is the watermark disappears when the text box gets focus. I'd like to make the watermark content disappear only when the user types the first character and then reappear if the text is cleared. Anyone have a good way to accomplish this?
I've tweaked the default style for you. Now the watermark shows with the (slightly darker) default system "inactive text" color by default, and the watermark's opacity transitions to 0.4 when it receives focus but has no content. Once it has text, the watermark disappears completely. Looks pretty good, I think:
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
<GradientStop Color="#ABADB3" Offset="0.05" />
<GradientStop Color="#E2E3EA" Offset="0.07" />
<GradientStop Color="#E3E9EF" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="TextBox_MouseOver" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#5794BF" Offset="0.05" />
<GradientStop Color="#B7D5EA" Offset="0.07" />
<GradientStop Color="#C7E2F1" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="TextBox_Focused" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#3D7BAD" Offset="0.05" />
<GradientStop Color="#A4C9E3" Offset="0.07" />
<GradientStop Color="#B7D9ED" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="TextBox_DisabledBorder" Color="#ADB2B5" />
<SolidColorBrush x:Key="TextBox_DisabledBackground" Color="#F4F4F4" />
<DataTemplate x:Key="DefaultWatermarkTemplate">
<ContentControl Content="{Binding}" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" Focusable="False" />
</DataTemplate>
<Style TargetType="{x:Type extToolkit:WatermarkTextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="3" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="WatermarkTemplate" Value="{StaticResource DefaultWatermarkTemplate}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type extToolkit:WatermarkTextBox}">
<Grid>
<Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="1" Background="{TemplateBinding Background}" />
<Border x:Name="MouseOverVisual" Opacity="0" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource TextBox_MouseOver}" CornerRadius="1" />
<Border x:Name="FocusVisual" Opacity="0" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource TextBox_Focused}" CornerRadius="1" />
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<ContentPresenter x:Name="PART_WatermarkHost"
Content="{TemplateBinding Watermark}"
ContentTemplate="{TemplateBinding WatermarkTemplate}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
IsHitTestVisible="False"
Margin="{TemplateBinding Padding}"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Visibility" TargetName="PART_WatermarkHost" Value="Visible" />
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsKeyboardFocusWithin" Value="True" />
<Condition Property="Text" Value="" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_WatermarkHost" Storyboard.TargetProperty="Opacity" To=".33" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_WatermarkHost" Storyboard.TargetProperty="Opacity" Duration="0:0:0.4" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<Trigger Property="Text" Value="">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_WatermarkHost" Storyboard.TargetProperty="Opacity" Duration="0:0:0.4" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_WatermarkHost" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="MouseOverVisual" Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="FocusVisual" Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource TextBox_DisabledBorder}" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource TextBox_DisabledBackground}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Easiest way to apply this throughout your application is to drop that XAML into Application.Resources in your App.xaml. Feel free to tweak the colors and opacity values.
I have the following XAML style for my button :
<Style TargetType="{x:Type Button}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="BtnBorder" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}" CornerRadius="5" VerticalAlignment="Center" BorderBrush="White" BorderThickness="0" ClipToBounds="True" HorizontalAlignment="Center">
<Grid Width="{Binding ElementName=BtnBorder, Path=ActualWidth}">
<Rectangle Name="BtnRect" RadiusX="6" RadiusY="5" Opacity="0.2" Fill="White" />
<Rectangle x:Name="progressIndicator" Width="0" HorizontalAlignment="Left" RadiusX="8" RadiusY="8" Margin="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Transparent" Offset="0" />
<GradientStop Color="#88FFFFFF" Offset="0.945" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="BtnCP" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BtnRect" Storyboard.TargetProperty="Opacity" From="0.25" To="0.5" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BtnRect" Storyboard.TargetProperty="Opacity" From="0.5" To="0.25" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="BtnBorder" Property="BorderThickness" Value="1.3" />
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="progressIndicator" Storyboard.TargetProperty="Width" From="0" To="300" Duration="0:0:5" AutoReverse="True" RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="BtnBorder" Property="BorderThickness" Value="1.5,0,1.5,0" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="True" />
<Condition Property="IsPressed" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="BtnBorder" Property="BorderThickness" Value="1.3" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can i control the animation of the Rectangle property of my button through code behind upon clicking the button.
The Rectangle named "progressIndicator" is to grow in width through animation when the user clicks the button.
Currently animation starts in Xaml. Why do you want to it in code-behind?
I have a button style defined like this:
<LinearGradientBrush x:Key="Brush_NavButtonBorder0" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#00383f47" Offset="0" />
<GradientStop Color="#FF383f47" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonBorder4" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#FF414f5a" Offset="0" />
<GradientStop Color="#11414f5a" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonBackground" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#FF3f505a" Offset="0" />
<GradientStop Color="#FF37454e" Offset="0.75" />
<GradientStop Color="#FF2f3c44" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonPressedBackground" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#FF3f505a" Offset="1" />
<GradientStop Color="#FF37454e" Offset="0.25" />
<GradientStop Color="#FF2f3c44" Offset="0" />
</LinearGradientBrush>
<Style x:Key="NavigationButton" TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="Gainsboro" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Background" Value="{StaticResource Brush_NavButtonBackground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}" x:Name="MainControlTemplate">
<Grid>
<Border x:Name="outerBorder" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder0}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" />
<Border Margin="1" CornerRadius="4" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder4}" Background="Transparent" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter TargetName="outerBorder" Property="BorderBrush" Value="Gray" />-->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="outerBorder"
Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
To="Gray"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource Brush_NavButtonPressedBackground}" />
<Setter TargetName="content" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform X="2.0" Y="2.0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisualStyle}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This style has a couple of problems:
1. When I MouseOver a button, all other buttons using this style react with the animation instead of just the button I'm over.
2. I would like to animate the color of the entire border instead of just the 0th gradient stop, but I can't seem to find a way to do this.
The commented line above the ColorAnimation section does almost exactly what I want except that it displays the gray BorderBrush immediately on MouseOver - I want it to display the gray BorderBrush with animation.
This seems like it should be pretty simple, but I can't figure out how to do this. Does anyone know how to do this the right way?
The reason it is changing the border on all the buttons is that you're actually changing the color in the gradient brush. And since the same gradient brush is shared among all the button instances with that style, the border for all the brushes changes.
There are a number of ways to resolve this, but one of which is to make the brush in question a resource of the style itself, so it won't be shared in the same way. The following code snippet demonstrates all you would need to change (remove Brush_NavButtonBorder0 from the top-level resources, and add it to the resources of the button style) :
EDIT: Including the full style with the updates
<Color x:Key="BorderColor">#00383f47</Color>
<!-- Other Brushes (NOT Brush_NavButtonBorder0) -->
<Style x:Key="NavigationButton" TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="Gainsboro" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Background" Value="{StaticResource Brush_NavButtonBackground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}" x:Name="MainControlTemplate">
<ControlTemplate.Resources>
<LinearGradientBrush x:Key="Brush_NavButtonBorder0" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="{StaticResource BorderColor}" Offset="0" />
<GradientStop Color="#FF383f47" Offset="1" />
</LinearGradientBrush>
</ControlTemplate.Resources>
<Grid>
<Border x:Name="outerBorder" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder0}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" />
<Border Margin="1" CornerRadius="4" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder4}" Background="Transparent" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter TargetName="outerBorder" Property="BorderBrush" Value="Gray" />-->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="outerBorder"
Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
To="Gray"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="outerBorder"
Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
To="{StaticResource BorderColor}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource Brush_NavButtonPressedBackground}" />
<Setter TargetName="content" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform X="2.0" Y="2.0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<!--<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisualStyle}" />
</Trigger>-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
This will mean that each button instance gets its own copy of the LinearGradientBrush, and your mouseover trigger animation is only affecting the one for the button that the mouse is over.
Again, there are a number of different ways to resolve this issue, but the code snippet above is the simplest I can think of given your current code.
Can somebody please extract a default template of a SurfaceCheckBox for me? I have tried using Blend 2 but failed miserably. The extracted template has some unresolved TargetName references.
I am trying to change the template so that the check mark is top aligned. It is centered vertically by default and there doesn't seem to be a direct way to change it.
[Edit] I have also tried Blend 3 which was a bit better but I am still missing "Glow" target and many references to it. This renders the template unusable unless all "Glow" references are removed. If I do that I get a working template but with no glow.
From Blend 4. Working this time, apperently you had to add a reference to Microsoft.Surface.Presentation.Generic.dll and then add
xmlns:Microsoft_Surface_Presentation_Generic="clr-namespace:Microsoft.Surface.Presentation.Generic;assembly=Microsoft.Surface.Presentation.Generic"
before you would get the Glow part when editing a style.
<!-- SimpleButtonFocusVisual is used to show keyboard focus around a SimpleButton control -->
<Style x:Key="SurfaceButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<!-- nothing, we don't want to make difference whether the element has focus or not-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--Common Brushes -->
<SolidColorBrush x:Key="NormalForegroundBrush"
Color="#FF000000" />
<SolidColorBrush x:Key="Default_FillBrush"
Color="#33A4B4BD"/>
<LinearGradientBrush x:Key="EdgeBrush"
EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="#7FFFFFFF"
Offset="0"/>
<GradientStop Color="#0CFFFFFF"
Offset="1"/>
</LinearGradientBrush>
<!-- Disabled Brushes are used for the Disabled look of each control -->
<SolidColorBrush x:Key="DisabledRenderBrush"
Color="#0CFFFFFF"/>
<SolidColorBrush x:Key="DisabledEdgeBrush"
Color="#33FFFFFF"/>
<SolidColorBrush x:Key="DisabledBevelBorder"
Color="#33000000"/>
<SolidColorBrush x:Key="DisabledForegroundBrush"
Color="#A5333333"/>
<SolidColorBrush x:Key="ShadowBorderBrush"
Color="#33000000"/>
<LinearGradientBrush x:Key="BevelBorderBrush"
EndPoint="0,0"
StartPoint="0,1">
<GradientStop Color="#66000000"
Offset="0"/>
<GradientStop Color="#33000000"
Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="RenderBrush"
EndPoint="0,0"
StartPoint="0,1">
<GradientStop Color="#26000000"
Offset="0"/>
<GradientStop Color="#4CFFFFFF"
Offset="1"/>
</LinearGradientBrush>
<!--Color for Glow-->
<Color x:Key="GlowColor">#FFFFFFFF</Color>
<!-- ButtonBase -->
<Style x:Key="SurfaceButtonStyle"
TargetType="{x:Type ButtonBase}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource SurfaceButtonFocusVisual}" />
<Setter Property="FontFamily"
Value="Segoe UI" />
<Setter Property="FontSize"
Value="10" />
<Setter Property="Foreground"
Value="{StaticResource NormalForegroundBrush}" />
<Setter Property="Background"
Value="{StaticResource Default_FillBrush}" />
<Setter Property="BorderBrush"
Value="{StaticResource EdgeBrush}" />
<Setter Property="BorderThickness"
Value="1,1,1,1" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Padding"
Value="15,6,15,6" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="Focusable"
Value="False" />
<Setter Property="MinWidth"
Value="30" />
<Setter Property="MinHeight"
Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<ControlTemplate.Resources>
<Storyboard x:Key="Press">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.1000000"
Value="-3,-3,-3,-3" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Release">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.0000000"
Value="1" />
<SplineDoubleKeyFrame KeySpline="0.5,0.5,0.5,1"
KeyTime="00:00:00.5000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.0000000"
Value="-3,-3,-3,-3" />
<SplineThicknessKeyFrame KeySpline="0.5,0.5,0.5,1"
KeyTime="00:00:00.5000000"
Value="1,1,1,1" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="Grid"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Border Margin="1,1,1,0"
x:Name="Shadow"
BorderThickness="0,0,0,1"
CornerRadius="6,6,6,6"
Padding="1,1,1,1"
BorderBrush="{StaticResource ShadowBorderBrush}" />
<Rectangle x:Name="Base"
Fill="{TemplateBinding Background}"
Stroke="{StaticResource BevelBorderBrush}"
StrokeThickness="1"
RadiusX="5"
RadiusY="5"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="1,1,1,1" />
<Rectangle x:Name="RenderOverlay"
Opacity="1"
Fill="{StaticResource RenderBrush}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="1"
RadiusX="4"
RadiusY="4"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="2,2,2,2" />
<Microsoft_Surface_Presentation_Generic:SurfaceShadowChrome Margin="1,1,1,1"
x:Name="Glow"
Color="{StaticResource GlowColor}"
CornerRadius="4,4,4,4"
Opacity="0" />
<ContentPresenter x:Name="Content"
RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter.RenderTransform>
<TranslateTransform X="0"
Y="-1" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Press}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Release}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsEnabled"
Value="True" />
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Fill"
Value="{StaticResource DisabledRenderBrush}"
TargetName="RenderOverlay" />
<Setter Property="Stroke"
Value="{StaticResource DisabledEdgeBrush}"
TargetName="RenderOverlay" />
<Setter Property="Stroke"
Value="{StaticResource DisabledBevelBorder}"
TargetName="Base" />
<Setter Property="BorderBrush"
Value="#00000000"
TargetName="Shadow" />
<Setter Property="Foreground"
Value="{StaticResource DisabledForegroundBrush}" />
<Setter Property="Background"
Value="#00FFFFFF" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="DisabledBackgroundBrush"
Color="#00000000"/>
<SolidColorBrush x:Key="DisabledBorderBrush"
Color="#33000000"/>
<RadialGradientBrush x:Key="CheckBox_RenderOverlayBrush"
GradientOrigin="0.627,0.5">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5"
CenterY="0.5"
ScaleX="-2.056"
ScaleY="-4.033"/>
<SkewTransform AngleX="0"
AngleY="0"
CenterX="0.5"
CenterY="0.5"/>
<RotateTransform Angle="90.17"
CenterX="0.5"
CenterY="0.5"/>
<TranslateTransform X="-0.016"
Y="-0.429"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#19000000"
Offset="0.205"/>
<GradientStop Color="#0CFFFFFF"
Offset="0.652"/>
</RadialGradientBrush>
<!--CheckBox Brushes-->
<LinearGradientBrush x:Key="CheckmarkIconGradientBrush"
EndPoint="0.5,0"
StartPoint="0.5,1">
<GradientStop Color="#FF292929"
Offset="0.5"/>
<GradientStop Color="#FF1B1B1B"
Offset="0.196"/>
</LinearGradientBrush>
<!-- CheckBox -->
<Style x:Key="SurfaceCheckBoxStyle1" TargetType="{x:Type my:SurfaceCheckBox}"
BasedOn="{StaticResource SurfaceButtonStyle}">
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="Foreground"
Value="{StaticResource NormalForegroundBrush}" />
<Setter Property="Padding"
Value="5,0,0,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type my:SurfaceCheckBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="Press">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.1000000"
Value="-3,-3,-3,-3" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Release">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.0000000"
Value="1" />
<SplineDoubleKeyFrame KeySpline="0.5,0.5,0.5,1"
KeyTime="00:00:00.5000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.0000000"
Value="-3,-3,-3,-3" />
<SplineThicknessKeyFrame KeySpline="0.5,0.5,0.5,1"
KeyTime="00:00:00.5000000"
Value="1,1,1,1" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Unchecked">
<DoubleAnimation Duration="00:00:00.2000000"
Storyboard.TargetName="Checkmark"
Storyboard.TargetProperty="Opacity"
To="0" />
</Storyboard>
<Storyboard x:Key="Checked">
<DoubleAnimation Duration="00:00:00.2000000"
Storyboard.TargetName="Checkmark"
Storyboard.TargetProperty="Opacity"
To="1" />
</Storyboard>
<Storyboard x:Key="ThreeStateEnter">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="ThreeStateMark"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="0.9" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="ThreeStateExit">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="ThreeStateMark"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.2000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<BulletDecorator MinHeight="30"
MinWidth="30"
Height="Auto"
Background="Transparent"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
x:Name="bulletDecorator">
<BulletDecorator.Bullet>
<Grid MinHeight="30"
MinWidth="30"
Width="30"
Height="30"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Rectangle x:Name="Base"
Fill="{TemplateBinding Background}"
Stroke="Transparent"
StrokeThickness="1"
RadiusX="7"
RadiusY="7"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="2,2,2,2" />
<Rectangle x:Name="Button"
Fill="{StaticResource Default_FillBrush}"
Stroke="{StaticResource BevelBorderBrush}"
StrokeThickness="1"
RadiusX="7"
RadiusY="7"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="2,2,2,2" />
<Rectangle x:Name="RenderOverlay"
Fill="{StaticResource CheckBox_RenderOverlayBrush}"
Stroke="{StaticResource EdgeBrush}"
StrokeThickness="1"
RadiusX="6"
RadiusY="6"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="3,3,3,3" />
<Microsoft_Surface_Presentation_Generic:SurfaceShadowChrome CornerRadius="6,6,6,6"
x:Name="Glow"
Color="{StaticResource GlowColor}"
Opacity="0"
Margin="-1,-1,-1,-1" />
<Path x:Name="Checkmark"
StrokeEndLineCap="Flat"
Fill="{x:Null}"
Stroke="{StaticResource CheckmarkIconGradientBrush}"
StrokeStartLineCap="Flat"
StrokeThickness="4"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="Auto"
Height="Auto"
Data="M4.2195036,10.149215 L9.4262573,13.556164 17.449568,5.9264725 17.449648,6.780637 9.3715682,13.987686 4.2190426,11.048134 z"
Opacity="0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="7.96,11.023,7.999,8.187"
Stretch="Fill" />
<Rectangle x:Name="ThreeStateMark"
Opacity="0"
Fill="{StaticResource CheckmarkIconGradientBrush}"
Stroke="{StaticResource BevelBorderBrush}"
StrokeThickness="1"
RadiusX="4"
RadiusY="4"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="6,6,6,6" />
</Grid>
</BulletDecorator.Bullet>
<Grid Margin="5,0,0,0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Grid Background="Transparent"
x:Name="ContentBox"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
x:Name="Content"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</Grid>
</BulletDecorator>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ThreeStateEnter}" />
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource ThreeStateExit}" />
</MultiTrigger.ExitActions>
<MultiTrigger.Conditions>
<Condition Property="IsThreeState"
Value="True" />
<Condition Property="IsChecked"
Value="{x:Null}" />
</MultiTrigger.Conditions>
</MultiTrigger>
<Trigger Property="IsChecked"
Value="False">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Unchecked}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Checked}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsChecked"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Checked}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Unchecked}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Press}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Release}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Fill"
TargetName="Button"
Value="{StaticResource DisabledBackgroundBrush}" />
<Setter Property="Stroke"
TargetName="Button"
Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Foreground"
Value="{StaticResource DisabledForegroundBrush}" />
<Setter Property="Fill"
TargetName="RenderOverlay"
Value="{StaticResource DisabledBackgroundBrush}" />
<Setter Property="Stroke"
TargetName="Checkmark"
Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Opacity"
TargetName="RenderOverlay"
Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm trying to animate a RadialGradientBrush in my application. I get the super helpful exception:
Additional information: 'System.Windows.Style' value cannot be assigned to property 'Style' of object 'System.Windows.Controls.Border'. '[Unknown]' property does not point to a DependencyObject in path '(0).(1).[0].(2)'. Error at object 'System.Windows.Style' in markup file 'Eng.Modules.Core;component/system/grid/systemgridview.xaml' Line 252 Position 51.
I know it's something wrong with the indirect property targeting or partial path qualification in my DoubleAnimation's Storyboard.TargetProperty attribute. Any ideas?
<Border>
<Border.Resources>
<RadialGradientBrush x:Key="SomeBrush">
<RadialGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gold" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Border.Resources>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Background" Value="{StaticResource SomeBrush}" />
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="SomeStoryBoard">
<Storyboard>
<!-- RIGHT HERE -->
<DoubleAnimation
Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].(GradientStop.Offset)"
From="0" To="1" Duration="0:0:1"
RepeatBehavior="Forever"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="SomeStoryBoard" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
The first problem is that you are setting the background to a gradient brush in your DataTrigger. Because this gets applied later, the animation won't be able to find the brush (hence the cryptic error about not finding a dependency property). So the first thing I did was set the border's background to the brush manually, rather than in the trigger.
The second problem was how you were setting up the target property. You don't need to use the parenthesis syntax- it works just fine as follows: Background.GradientStops[0].Offset.
With these changes the border animates perfectly; here is the final mark-up:
<Border>
<Border.Background>
<RadialGradientBrush>
<RadialGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gold" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Border.Background>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="SomeStoryBoard">
<Storyboard>
<!-- RIGHT HERE -->
<DoubleAnimation
Storyboard.TargetProperty="Background.GradientStops[0].Offset"
From="0" To="1" Duration="0:0:1"
RepeatBehavior="Forever"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="SomeStoryBoard" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
My Answer as per the comments in the code sample.
I've removed the MultiDataTrigger from my first post, as I can't get this working myself with bound collections. I may have to ask this to see if anyone has an answer to the issue.
<Grid>
<Grid.Resources>
<!-- Don't use a ControlTemplate. This destroys your control structure,
which doesn't make sense if all you want to do is animate the background. -->
<Style x:Key="MyAnimatedFeatureStyle" TargetType="Button">
<Style.Resources>
<RadialGradientBrush x:Key="GoldRadialGradientBrush">
<RadialGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gold" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
<Storyboard RepeatBehavior="Forever" AutoReverse="False" x:Key="SomeStoryBoard">
<DoubleAnimation Storyboard.TargetProperty="Background.GradientStops[0].Offset" From="0" To="1" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True" />
</Storyboard>
</Style.Resources>
<Style.Triggers>
<!-- Your primary binding condition. Whatever this may be. -->
<DataTrigger Binding="{Binding Path=IsSOMTHINGSET}" Value="true" >
<!-- The Background is here in the setter, because we only want the background colored and animated on the binding condition. -->
<Setter Property="Background" Value="{StaticResource GoldRadialGradientBrush}" />
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="BorderStoryBoard" Storyboard="{StaticResource SomeStoryBoard}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="BorderStoryBoard" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button Style="{StaticResource MyAnimatedFeatureStyle}" />
</Grid>
I actually developed a solution to the problem just as Charlie posted his. It looks like we came up with close to the same thing. Just posting mine for reference:
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Resources>
<RadialGradientBrush x:Key="GoldRadialGradientBrush">
<RadialGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gold" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
<Storyboard x:Key="SomeStoryBoard">
<DoubleAnimation
Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].Offset"
From="0" To="1" Duration="0:0:1"
RepeatBehavior="Forever"
AutoReverse="True" />
</Storyboard>
</ControlTemplate.Resources>
<Grid>
<Border Background="{StaticResource GoldRadialGradientBrush}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="BorderStoryBoard" Storyboard="{StaticResource SomeStoryBoard}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="BorderStoryBoard" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>