Activate Storyboard on Visibility Changed - c#

Currently I have an Image that I pulse when it is loaded. I want to rather activate the Storyboard when I change the Visibility of the Image. But I see that Image.Triggers have to be EventTriggers.
Which event do I need to hook into?
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MandateErrorImage"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.1" Duration="0:0:0.5"
AutoReverse="True" RepeatBehavior="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>

In WPF there is an event UIElement.IsVisibleChanged but is a CLR event, not a routed event, therefore in EventTrigger can not be used.
In this case use IsVisible property in DataTrigger like this:
<Window.Resources>
<Style x:Key="AnimationImageStyle" TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=IsVisible}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="1.0" To="0.1"
Duration="0:0:0.5"
AutoReverse="True"
RepeatBehavior="0:0:2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Image Name="TestImage"
Style="{StaticResource AnimationImageStyle}"
Source="Enter.jpg"
Width="400"
Height="400" />
</Grid>

If you want to animate on a DependencyProperty or bound value you will need to create a Style for your image and put the animation in the style.
The following Style will perform your animation when the Visibility of your image is set to Visible:
<Style x:Key="FlashingImageStyle" TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.1" Duration="0:0:0.5"
AutoReverse="True" RepeatBehavior="0:0:2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>

Related

I added some animations on the button by style triggers, but the second animation on the same property doesn't work

Here is my XAML code.
<Window x:Class="TestWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWpf"
mc:Ignorable="d"
Title="MainWindow" Height="320" Width="340">
<Window.Resources>
<QuadraticEase x:Key="easing" EasingMode="EaseOut"/>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Label Name="label"/>
<Button Content="Hello" Width="100" Height="45">
<Button.Style>
<Style TargetType="Button">
<Style.Resources>
<Storyboard x:Key="press" x:Name="press">
<DoubleAnimation Storyboard.TargetProperty="Width" To="125" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="50" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="hover" x:Name="hover">
<DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="leave" x:Name="leave">
<DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource press}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource leave}"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</Window>
You can see that I specified a style for the button, and added some triggers that can do some animation when I move the mouse or click the mouse button.
When I move my mouse to the button, the button size turns 120x45. But when I pressed the mouse button after that, nothing happened.
What I want:
Button default size is 100x45
When the mouse is hovering, the button size will change to 120x45 (width increased by 20) through animation, and when not hovering, the size will be restored
When the mouse is pressed, the size will change to 125x50 through animation (the width and height increase by 5), and when the mouse is released, the size will restore
even if I add StopStoryboard before BeginStoryboard, it will throw an exception that the Storyboard cannot be found.
I ran your XAML with these changes and everything works fine for me:
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Label x:Name="label" Content="LABEL"/>
<Button Content="Hello" Width="100" Height="45">
<Button.Style>
<Style TargetType="Button">
<Style.Resources>
<Storyboard x:Key="press" x:Name="press">
<DoubleAnimation Storyboard.TargetProperty="Width" To="200" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="100" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="hover" x:Name="hover">
<DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="leave" x:Name="leave">
<DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<StopStoryboard BeginStoryboardName="IsMouseOverTrue"/>
<BeginStoryboard Storyboard="{StaticResource press}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="IsMouseOverTrue" Storyboard="{StaticResource hover}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource leave}"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>

Animatint BlurEffect in a style works but animating DropShadowEffect causes error?

I am trying to animate a DropShadowEffect I have applied to one grid and a BlurEffect that I have applied to another grid.
The blur animation seems to work fine and this is the code.
<Style x:Key="BluredGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="extentions:GridExtention.IsBlured" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).Radius" From="0" To="10" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).Radius" From="10" To="0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Grid Background="{DynamicResource BrHostBackground}">
<Grid extentions:GridExtention.IsBlured="{Binding BackgroundIsBlured}" Style="{StaticResource BluredGridStyle}">
<Grid.Effect>
<BlurEffect x:Name="BlurEffect" Radius="0"/>
</Grid.Effect>
</Grid>
</Grid>
But when I try with the drop shadow I get errors. Here is my initial code.
<Style x:Key="DropShaodowGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).BlurRadius" From="0" To="80" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).BlurRadius" From="80" To="0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Grid Visibility="{Binding HardwareLoadingVisibility}">
<Grid x:Name="grid" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" Width="550" Height="250" Style="{DynamicResource DropShaodowGridStyle}">
<Grid.Effect>
<DropShadowEffect ShadowDepth="0" Opacity="0.8"/>
</Grid.Effect>
</Grid>
</Grid>
This generates the following error
InvalidOperationException: Cannot resolve all property references in the property path '(Effect).BlurRadius'. Verify that applicable objects support the properties.
If I change the property to (Effect).Radius I get the same error.
I also tried changing the property to (UIElement.Effect).(DropShadowEffect.BlurRadius) which generated this error
InvalidOperationException: 'Effect' property does not point to a DependencyObject in path '(0).(1)'.
Looks like I found the answer.
I had to assign a default value to the property in the style.
<Style x:Key="DropShaodowBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" BlurRadius="0"></DropShadowEffect>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).BlurRadius" From="0" To="80" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).BlurRadius" From="80" To="0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>

Polygon Animation won't work in c#

I am having a small Problem in C#. I want to have a Polygon I drew in WPF to be animated on hover.
I successfully drew the polygon like this:
<Polygon Fill="#FF767676" Points="0,8,12,0,12,16" Margin="30" Style="{DynamicResource BackAndForth}"/>
I then defined a style
<Style x:Key="BackAndForth" TargetType="{x:Type Polygon}">
<Setter Property="Opacity" Value="0.6" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" From="0.6" To="1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" From="1" To="0.6" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
Somehow this won't work. The setter property in line 2 works. But somehow the animation won't get triggered. I already looked it up but polygons have a IsMouseOver Property.
The exact same code works perfecty on buttons (with a proper target type).
Any ideas what I am missing?

WPF Animation Triggers Regardless of Property Value

I am trying to make a smooth fade in/out animation for an inline alert box in a WPF form. The problem is that the animation seems to run even when the property is not set to the value expected in the trigger. I've put a breakpoint in the converter method and it never returns anything except Visibility.Hidden, however the trigger on Visibility.Visible is firing the animation of the Height property (may or may not be firing the one on opacity too but I couldn't tell since the Grid is Visibility.Hidden).
Here is the style:
<Style TargetType="Grid" x:Key="AlertStyle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="00:00:02"
BeginTime="00:00:00"
To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Height"
Duration="00:00:01"
BeginTime="00:00:00"
To="60.0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
The Grid in question is here:
<Grid DockPanel.Dock="Top"
Visibility="{Binding Path=Message, Converter={StaticResource NullToVis}}"
Style="{StaticResource AlertStyle}">
<ContentPresenter Content="{Binding Path=Message, Mode=OneWay}"/>
</Grid>
The Value Converter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value == null) ? Visibility.Hidden : Visibility.Visible;
}
When I add a second trigger to the <Style.Triggers> element neither animation ever runs.
The second trigger:
<Trigger Property="Visibility" Value="Hidden">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="00:00:01"
BeginTime="00:00:00"
To="0.0" />
<DoubleAnimation Storyboard.TargetProperty="Height"
Duration="00:00:02"
BeginTime="00:00:00"
To="0.0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
I've never tried to do anything related to Animation in WPF before and I've found similar styles peppered all over the internet but haven't been able to modify any successfully to get them to do what I'm trying to accomplish.
Try this:
<Style TargetType="Grid" x:Key="AlertStyle">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard Name="Storyboard">
<Storyboard BeginTime="00:00:00">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="00:00:02" To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Height"
Duration="00:00:01" To="60.0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard" />
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
If that doesn't work, then you can try using a DataTrigger with a custom Boolean value... you can't go too far wrong with that.

Load all the effect of storyboard until it's finish

I have an image which when pressed by user, the opacity will fade until value 0. But the effect only continues if user press and hold the image. Is there a possible way to change the code to: When user press, and without holding the press, the opacity fading effect will stay? I wish to do it in XAML.
<EventTrigger RoutedEvent="Button.Click" SourceName="press">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource showA}"/>
</EventTrigger.Actions>
</EventTrigger>
<Button Grid.Column="5" Command="{Binding Path=PressC}" CommandParameter="dot" Style="{StaticResource TransparentButton}">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="image5" Source="/W;component/Images/t.png" Height="100" />
<Image Name="pressed5" Source="/W;component/Images/T.png" Height="100" Width="200" Margin="-23,-136,-21,0" Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="pressed5" Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Setter Property="Panel.ZIndex" Value="999"/>
<Setter TargetName="pressed5" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
Can you show your full xaml? Because Image does not have IsPressed property and it is not clear how it works for you.
Similar code for button works as expected:
<Button Background="Aquamarine">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
And for Image it works too with EventTrigger:
<Image Source="d:\123.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Image.Style>

Categories