WPF TabItem style when mouse left button is down - wpf

I am defining a Style for WPF TabControl TabItem.
I want to show a slight "pushed down" effect on TabItem when mouse (left button) is pressed down and the TabItem is not selected but I cannot find the Trigger for this.
I have tried to define a MultiTrigger with IsMouseLeftButtonDown and IsPressed properties but neither one is recognized.
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="bd" BorderThickness="1,1,0,0">
<Grid>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"
ContentSource="Header"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseLeftButtonDown" Value="True" /> <!--NOT RECOGNIZED-->
<Condition Property="IsSelected" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="bd" Property="Background" >
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Yellow" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How to set a Trigger that gets into action when mouse left button is pressed down on a TabItem ?
EDIT
I tried EventTrigger but I don't see any effect with the below
<EventTrigger RoutedEvent="UIElement.PreviewMouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Green" Duration="0:0:3" />
</Storyboard>
<BeginStoryboard/>
<EventTrigger/>
Can it be achieved with this way somehow ?

This example shows you, how to work with EventTriggers.
Note
You might have to set your Highlighting-Logic fully in those Triggers, since values are overridden everytime, the Trigger fires.
<EventTrigger RoutedEvent="PreviewMouseDown" >
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard >
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background" Duration="0:0:3" BeginTime="0" AutoReverse="True">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Brushes.Green}" />
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="PreviewMouseUp" >
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard >
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="bd" Storyboard.TargetProperty="Background" Duration="0:0:3" BeginTime="0" AutoReverse="True">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Brushes.Transparent}" />
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>

Related

WPF ColorAnimation alternative

What I'm trying to do is set the background of control to a gradient when the ToggleButton its part of is enabled. This would be easy but this is WPF and for whatever reason will not let me use a LinearGradientBrush in the ColorAnimation.
All I'm looking for is just an alternative to accomplish something similar thing to what I've attempted to do below.
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="DarkGray" Style="{StaticResource ToggleBrushOn}" x:Name="Pill">
<Border x:Name="Circle" Background="#FFFFFF" Width="22" Height="22" CornerRadius="22" Margin="35,5,5,5" HorizontalAlignment="Right"/>
<Border.Clip>
<RectangleGeometry Rect="0,0,65,32" RadiusX="15" RadiusY="32"/>
</Border.Clip>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="Pill" Storyboard.TargetProperty="(Control.Background)" To="{StaticResource tbGradient}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="Pill" Storyboard.TargetProperty="(Control.Background)" To="DarkGray"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
When using <ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="Pill" Storyboard.TargetProperty="(Control.Background)" To="{StaticResource tbo}"/> I receive the following error: ArgumentException: 'System.Windows.Media.LinearGradientBrush' is not a valid value for property 'To'.
tbGradient is supposed to be a Color:
<Color x:Key="tbGradient">Blue</Color>
You could then animate the background using the Trigger like this:
<Trigger Property="IsChecked" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="Pill" Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" To="{StaticResource tbGradient}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="Pill" Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" To="DarkGray"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
If you want a gradient background, you could set the Background to a LinearGradientBrush and animate a GradientStop, e.g.:
<ToggleButton>
<ToggleButton.Resources>
<Color x:Key="tbGradient">Blue</Color>
</ToggleButton.Resources>
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="Pill">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop x:Name="gs" Color="DarkGray" Offset="0.5" />
</LinearGradientBrush>
</Border.Background>
<Border x:Name="Circle" Background="#FFFFFF" Width="22" Height="22" CornerRadius="22" Margin="35,5,5,5" HorizontalAlignment="Right"/>
<Border.Clip>
<RectangleGeometry Rect="0,0,65,32" RadiusX="15" RadiusY="32"/>
</Border.Clip>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="gs" Storyboard.TargetProperty="Color" To="{StaticResource tbGradient}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="gs" Storyboard.TargetProperty="Color" To="DarkGray"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>

WPF - ToggleButton Template Trigger stop firing after first call

I have custom template for ToggleButton with triggers targeted for providing clear visual difference between Checked and Unchecked state.
Main concept:
Trigger 1. When Togglebuton is Unchecked and MouseOver = false: FontSize should be 13, FontWeight - Normal.
Trigger 2. When Togglebuton is Unchecked and MouseOver = true: FontSize should be 14, FontWeight - Normal.
Trigger 3. When Togglebuton is Checked: FontSize should be 15, FontWeight - Bold.
Everything is working fine, but after first toggleButton check/uncheck sequence
trigger 2 stops to fire and ToggleButton does not change appearence on MouseOver = true any more.
Here is my actual XAML.
<Style TargetType="{x:Type ToggleButton}" x:Key="DefaultToggleButtonStyle">
<Style.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2"
SnapsToDevicePixels="true"
Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
StrokeThickness="1"
StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="Background" Value="{DynamicResource ButtonColor}" />
<Setter Property="Foreground" Value="{DynamicResource EditAreaColor}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="1" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="FontSize" Value="13" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ControlTemplate.Resources>
<Style TargetType="Border" x:Key="MainBorderStyle">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="UseLayoutRounding" Value="True" />
</Style>
</ControlTemplate.Resources>
<Grid>
<Border Background="Black" Opacity="0.5">
<Border.Effect>
<BlurEffect Radius="7" />
</Border.Effect>
</Border>
<Border x:Name="upperSurfaceBorder" Background="{TemplateBinding Background}" Style="{StaticResource MainBorderStyle}">
<Border x:Name="mouserOverHl" Background="Transparent"
Style="{StaticResource MainBorderStyle}"
BorderThickness="0.5" BorderBrush="{StaticResource MainNormal}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Border>
<Border Background="Transparent" Style="{StaticResource MainBorderStyle}" x:Name="disabledOverlay" />
</Grid>
<ControlTemplate.Triggers>
<!--MouseOver-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="False"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="FontSize">
<DoubleAnimation To="14" Duration="0:0:.3">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetProperty="FontSize">
<DoubleAnimation To="13" Duration="0:0:.3">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<!--IsChecked-->
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Trigger.Setters>
<Setter Property="Background" Value="{StaticResource MainVeryDark}"/>
</Trigger.Setters>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="FontWeight">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<FontWeight>Bold</FontWeight>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetProperty="(ToggleButton.Background).(SolidColorBrush.Color)">
<ColorAnimation Duration="0:0:0.1" To="#002f67">
<ColorAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</ColorAnimation.EasingFunction>
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetProperty="FontSize">
<DoubleAnimation To="15" Duration="0:0:0">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="FontWeight">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<FontWeight>Normal</FontWeight>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetProperty="FontSize">
<DoubleAnimation To="13" Duration="0:0:0">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<!--Pressed-->
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetName="upperSurfaceBorder" TargetProperty="Margin">
<ThicknessAnimation Duration="0:0:0.1" To="2 2 -2 -2">
<ThicknessAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetName="upperSurfaceBorder"
TargetProperty="Margin">
<ThicknessAnimation Duration="0:0:0.1"
To="0 0 0 0">
<ThicknessAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<!--Disabled-->
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.3" Storyboard.TargetName="disabledOverlay"
Storyboard.TargetProperty="Background.Color" To="#55FFFFFF">
<ColorAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</ColorAnimation.EasingFunction>
</ColorAnimation>
<DoubleAnimation Duration="0:0:0.3" Storyboard.TargetProperty="Foreground.Opacity" To="0.6" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.3" To="Transparent" Storyboard.TargetName="disabledOverlay" Storyboard.TargetProperty="Background.Color">
<ColorAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</ColorAnimation.EasingFunction>
</ColorAnimation>
<DoubleAnimation Duration="0:0:0.3" Storyboard.TargetProperty="Foreground.Opacity" To="1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
<Setter Property="Visibility" Value="Visible" TargetName="disabledOverlay" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any suggestions what's wrong?
Thanks in advance!
Your Main problem is in Trigger 3. I think EnterActions and ExitActions have not feeling good with IsChecked Property. I don't know why.
you must take another way to writing this trigger.
Well, as RezaNoei suggested, the problem was in ExitActions of Trigger 3. I solved this issue by removing of "To" property of font's size animation. This decision was inspired by this topic.

WPF Button Style with textBlock contentTemplate, how to change textblock foreground colour storyboard

I have the following button style. My question, how can I change the textblock's text colour when the button is not enabled? I tried setting "ButtonTextBlock" value through the storyboard but it cannot seem to access it. Thanks.
<Style TargetType="{x:Type Button}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Viewbox>
<!-- TODO change this textblocks colour depending on IsEnabled -->
<TextBlock x:Name="ButtonTextBlock" HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="0,2,0,2">
<ContentPresenter Content="{TemplateBinding Content}" >
</ContentPresenter>
</TextBlock>
</Viewbox>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="{StaticResource ButtonBorderBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
<GradientStop x:Name="BackgroundGradientStop1" Offset="0" Color="{StaticResource AlbumScrollButtonNormal1}" />
<GradientStop x:Name="BackgroundGradientStop2" Offset="1" Color="{StaticResource AlbumScrollButtonNormal2}" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<!-- Button Disabled -->
<Trigger Property="IsEnabled" Value="False">
<!-- Disabled -->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="ButtonDisabled">
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonDisabled1}"
Duration="0" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonDisabled2}"
Duration="0" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<!-- Enabled -->
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard x:Name="ButtonEnabled">
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonNormal1}"
Duration="0" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonNormal2}"
Duration="0" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<!-- Mouse Over and Mouse leave -->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsEnabled" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<!-- Mouse Over -->
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="MouseOverAnimation">
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonMouseOver1}"
Duration="0:0:0:0.1" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonMouseOver2}"
Duration="0:0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<!-- Mouse Leave -->
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard x:Name="MouseLeaveAnimation" FillBehavior="Stop">
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonNormal1}"
Duration="0:0:0:0.1" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonNormal2}"
Duration="0:0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<!-- Mouse Press -->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsEnabled" Value="True" />
<Condition Property="IsPressed" Value="True" />
</MultiTrigger.Conditions>
<!-- Mouse Down -->
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="MouseDownAnimation" >
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonPressed1}"
Duration="0:0:0:0.1" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonPressed2}"
Duration="0:0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<!-- Mouse Up -->
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard x:Name="MouseUpAnimation" FillBehavior="Stop">
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop1"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonMouseOver1}"
Duration="0:0:0:0.1" />
<ColorAnimation Storyboard.TargetName="BackgroundGradientStop2"
Storyboard.TargetProperty="Color"
To="{StaticResource AlbumScrollButtonMouseOver2}"
Duration="0:0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can animate Foreground.Color of the Button when IsEnabled=False. Also there is no need for ContentTemplate in your Style. You can move ViewBox to ControlTemplate and remove ContentTemplate
<ControlTemplate TargetType="{x:Type Button}">
<Border ...>
<Viewbox>
<ContentPresenter ... />
</Viewbox>
</Border>
<ControlTemplate.Triggers>
<!-- Button Disabled -->
<Trigger Property="IsEnabled" Value="False">
<!-- Disabled -->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="ButtonDisabled">
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="Green" Duration="0:0:0.1"/>
</Storyboard>
<!--other animations-->
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<!--other triggers-->
</ControlTemplate.Triggers>
</ControlTemplate>

Stop / start storyboard animation based on Visibility

I have an animation that currently starts when a Control is loaded (the animation is essentially a waiting spinner, that is applied to an empty ContentControl).
The animation however will constantly spin taking up resources. What I'd like is for the animation to start / stop based on whether the animation control is visible or not, is this possible?
<Canvas.Triggers>
<EventTrigger RoutedEvent="ContentControl.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="SpinnerRotate"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:01.3"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
I must have this working for both Silverlight and WPF.
I have created an example of spinning an Ellipse based on the Visibility property. Perhaps you can use something from this.
<Canvas>
<Ellipse x:Name="Circle" Width="30" Height="30"
Canvas.Left="50"
Canvas.Top="50">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Fill>
<Ellipse.RenderTransform>
<RotateTransform x:Name="SpinnerRotate" CenterX="15" CenterY="15"/>
</Ellipse.RenderTransform>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard x:Name="SpinStoryboard">
<Storyboard >
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
From="0" To="360" Duration="0:0:01.3"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="SpinStoryboard"></StopStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Canvas>
Might not be elegant, but works.
<Border x:Name="square" Height="20" Width="20" Background="Aqua">
<Border.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard x:Name="spinner">
<DoubleAnimation
Storyboard.TargetName="square"
Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:01.3"
AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={RelativeSource Self}, Path=Visibility}" Value="{x:Static Visibility.Collapsed}">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="spinner"/>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>

WPF IDataErrorInfo icon location right

I have a validation template as below. But we can set the error icon either inside control or left of the control. Can you please tell me how can i make it blink at the right of the control (Outside the textBox and right)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Storyboard x:Key="FlashErrorIcon">
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.2000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4000000" Value="{x:Static Visibility.Hidden}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.6000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8000000" Value="{x:Static Visibility.Hidden}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Style x:Key="myErrorTemplate" TargetType="Control">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Ellipse DockPanel.Dock="Left"
ToolTip="{Binding ElementName=myTextbox,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
Width="15" Height="15"
Margin="-25,0,0,0"
StrokeThickness="1" Fill="Red" >
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFFA0404" Offset="0"/>
<GradientStop Color="#FFC9C7C7" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
<TextBlock DockPanel.Dock="Left"
ToolTip="{Binding ElementName=myControl,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
Foreground="White"
FontSize="11pt"
Margin="-15,5,0,0" FontWeight="Bold">!
<TextBlock.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="myControl"/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource myErrorTemplate}" />
Change the location of the error icon via modifications to the template.

Resources