Visibility fadeout and fade in infinite loop - wpf

I have some Grid with some element inside and I want to add it some fade in fade out effect with Visibility property in infinite loop base on some bool property.
This is what I have tried:
<Grid.Style>
<Style TargetType="FrameworkElement">
<Setter Property="Visibility" Value="Visible"/>
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Collapsed">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0"
To="1.0"
Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
Currently I cannot see my Grid at all.

There are a few issues in your style:
You do not see the Grid, because you set the initial Opacity to 0.
You can remove both of your Setters, because those are the default values
Making the trigger dependent on Visibility does not work, because when it is set to Collapsed, the Grid is already invisible, so the animation is not even visible.
There is no exit action to make the Grid fade in again.
You could solve the issues by exposing a property (here MyAnimationTriggerProperty) that you use as trigger for the animation. Depending o your actual application this could also be the IsChecked state of another control. Then you can add an ObjectAnimationUsingKeyFrames to set the Visibility at the end of the animation.
<Style TargetType="FrameworkElement">
<Style.Triggers>
<DataTrigger Binding="{Binding MyAnimationTriggerProperty}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="1.0"
To="0.0"
Duration="0:0:0.2"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0"
To="1.0"
Duration="0:0:0.2"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>

Related

How do I set the Background after a Storyboard ColorAnimation complete in XAML?

How do I set the Background after a Storyboard ColorAnimation completes in XAML?
My ColorAnimation runs which makes Background flash red but after it returns to the original background colour (white) I would like it to remind red but i can't see how to do this.
My xaml is below - thanks
<Grid Name="cell" Background="White">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding DataItem.ControlValue, Converter={StaticResource IsNotNullOrEmptyConverter}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="Blink" >
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Blink" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
Set AutoReverse to False on your ColorAnimation if you don't want it to revert back to original value i.e White.
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="False"/>
UPDATE
Add another ColorAnimation in your Storyboard which will begin after your first ColorAnimation completes may be after 4 sec interval.
<BeginStoryboard>
<Storyboard x:Name="Blink">
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
Duration="0:0:1" BeginTime="0:0:4"/>
</Storyboard>
</BeginStoryboard>

WPF : Animating Width of an Control alternately with start value

I have an image whose width should be animated from 0 to 30 pixels when a boolean property changes to true an back from 30 to 0 pixels if the property switches back to false.
In general, this works with this XAML code:
<Image.Style>
<Style TargetType="{x:Type Image}">
<!-- <Setter Property="Width" Value="0"/> -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=AIM, Path=IsDeletingEnabled}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- Animate the Width of the Image from 0 to 30px within 300ms-->
<DoubleAnimation Storyboard.TargetProperty="Width" From="0" To="30" Duration="0:0:0.3"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<!-- Animate the Width of the Image from 30 to 0px within 300ms-->
<DoubleAnimation Storyboard.TargetProperty="Width" From="30" To="0" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
The problem is, that before the Property IsDeletingEnabled switches to true the first time, the images witdh is 30px and it is visible. When I uncomment the first setter and set the Witdh to 0px by default (or the Visibilityto Hidden), the image isn't shown at startup but disappears instantly after switching IsDeletingEnabled from trueto fals. In this case, no animation is visible.
Has anywone a solution how I can set the Visibilityto Hiddenor the Witdhto 0px at startup without hiding the DataTrigger.ExitAction ?
Do you explicitly need to set the Visibility to Hidden if you're setting the Width to 0? A zero-width element and a hidden element look the same onscreen.
Your exit action is not being 'hidden', what's happening is the DataTrigger is 'undoing' the <Setter Property="Visibility" Value="Visible"/> in addition to running the exit action. But since the visibility has immediate effect you don't see the exit action being run.
Your enter action needs to both Visibility=Visible and start the expanding animation. Your exit action needs to perform the shrinking animation, but wait to set Visibility=Visible until after it's complete. You can do this with an ObjectAnimationUsingKeyFrames animation:
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Hidden"/>
<Setter Property="Width" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsShown}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- Animate the Width of the Image from 0 to 30px within 300ms-->
<DoubleAnimation Storyboard.TargetProperty="Width" From="0" To="30" Duration="0:0:0.3"/>
<!-- Set the Image to Visible immediately -->
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<!-- Animate the Width of the Image from 30 to 0px within 300ms-->
<DoubleAnimation Storyboard.TargetProperty="Width" From="30" To="0" Duration="0:0:0.3" />
<!-- After 300ms, hide the Image -->
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0.3" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Hidden</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>

Fade out animation on DockPanel

<DockPanel Name="MyPanel" IsVisibleChanged="MyPanel_IsVisibleChanged">
<DockPanel.Triggers>
<EventTrigger RoutedEvent="IsVisibleChanged"> // error here
</EventTrigger>
</DockPanel.Triggers>
</DockPanel>
Above is my dockpanel xmal code. Because IsVisibleChanged is not a RoutedEvent I can not add in the EventTrigger this code:
<Storyboard x:Key="hideMe">
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" To="0.0"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="showMe">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:5" To="0.75"/>
</Storyboard>
I try to give a fade out animation to my dockpanel.
Instead of using an event trigger, I would use a normal trigger to check the value of the Visibility property of the DockPanel.
You can create a style on the DockPanel to do it, like this:
<DockPanel Name="MyPanel">
<DockPanel.Style>
<Style TargetType="DockPanel">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<!-- Set storyboard to run when DockPanel is set visible here: -->
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<!-- Set storyboard to run when DockPanel is no longer set visible here: -->
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
</DockPanel>

Setting a ViewModel boolean property inside a storyboard

I have a storyboard that's triggered by a property in the ViewModel, this trigger the animation to start.
But how do I set the "Saved" property back to False when it is done with the animation (to trigger the ExitAction.)
<Style TargetType="TextBlock" x:Key="FadeInOut">
<Style.Triggers>
<DataTrigger Binding="{Binding Saved}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1" From="0" To="1" />
<!-- set "Saved" to false when done -->
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1" From="1" To="0" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
If you can navigate to your property i would recommend a BooleanAnimationUsingKeyFrames with a discrete frame at your end-time.
<BooleanAnimationUsingKeyFrames
Storyboard.TargetProperty="DataContext.Saved"
FillBehavior="HoldEnd">
<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:1" />
</BooleanAnimationUsingKeyFrames>
Since you use a binding to Saved i assume using the DataContext should work.
You can use the ObjectAnimationUsingKeyFrames to set the property. I'm not quite sure if you could use other animations but this is the one I recently used.
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Saved">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<system:Boolean>False</system:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>

How can I make a XAML Trigger call a XAML Style?

This style correctly fades my toolbar in or out based on the changing of a ViewModel Property:
<Style x:Key="PageToolBarStyle" TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding PageToolBarVisible}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0.0"
To="1.0"
Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1.0"
To="0.0"
Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
<Trigger Property="Opacity" Value="0">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
However, when the application loads the status of the toolbar (faded out or in) is not in sync with the value of the ViewModel property (true or false). So I want to force this style to be executed upon loading the window, what is the syntax to do this, here is pseudo code of what I want to do:
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<!-- PSEUDO-CODE: -->
<ExecuteTriggerStyle StyleToExecute="{StaticResource PageToolBarStyle}"/>
</EventTrigger.Actions>
</EventTrigger>
</Window.Triggers>

Resources