1

I am creating a Style containing Animation's, which can then be inherited to specific control styles, which are applied automatically.

Actually I'm struggling on implementing a simple Animation:

  • When Visibility is changed to Visible, Opacity is changed from 0 to 1
  • When Visibility is changed to something else than visible, Opacity is doing the inverse thing

So far I got:

<Style x:Key="BaseAnimationsStyle">
    <Style.Triggers>
        <Trigger Property="FrameworkElement.Visibility" Value="Visible">
            <Trigger.EnterActions> <!-- this works -->
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions><!-- this doesn't -->
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style>

If the above Style is set on a control it then has the following behaviour:

When the control's Visibility is set to Visible the transition is working correctly, meaning it is fading in.

Issue: When the control's Visibility is set to Hidden (or even Collapsed), the control will be hidden instantly without fading.

My guess is, that there is some default behaviour to be overridden of how FrameworkElement's deal with Visibility-Changes.

LuckyLikey
  • 3,504
  • 1
  • 31
  • 54
  • 1
    Could you please clarify your issue? Do you see the control when it is hidden? – mm8 Apr 11 '17 at 09:31
  • @mm8 I guess you might see clearly now :) – LuckyLikey Apr 11 '17 at 09:43
  • 1
    That's because after element Visibility is set to Collapsed or Hidden - it does not make sense to animate opacity (or anything else) on it - it's now, well, not visible any more :) – Evk Apr 11 '17 at 09:50
  • @Evk Exactly.. and that's the issue.. it should be invisible **after** the animation – LuckyLikey Apr 11 '17 at 09:51
  • Don't set the Visibility property then. You could set some attached property of yours and then animate the opacity property. – mm8 Apr 11 '17 at 09:52
  • Possible duplicate of [WPF Fade Animation](http://stackoverflow.com/questions/1013817/wpf-fade-animation) – Rekshino Apr 11 '17 at 10:19

3 Answers3

2

Setting the Visibility property to Collapsed or Hidden will make the element invisible right away but instead of setting the Visibility property you could set some attached property of yours and then animate the Opacity property to fade out the element. Please refer to the following link for more information and an example.

WPF: How To Animate Visibility Property?: http://blogs.microsoft.co.il/arik/2010/02/08/wpf-how-to-animate-visibility-property/ https://www.codeproject.com/Articles/57175/WPF-How-To-Animate-Visibility-Property

WPF Fade Animation

mcalex
  • 6,628
  • 5
  • 50
  • 80
mm8
  • 163,881
  • 10
  • 57
  • 88
0

I have solved my issue with the information provided by @mm8's Answer.

Basically I added the VisibilityAnimation Class to my Project. I then simply created my Base-Style using the Provided Attached-Property inside a Setter.

<!-- Animations -->
<Style x:Key="BaseAnimationsStyle">
    <Setter Property="anim:VisibilityAnimation.AnimationType" Value="Fade" />
</Style>


<!-- This adds the Visibility Animation to every Grid which has access to this resource -->
<Style TargetType="{x:Type Grid}" BasedOn="{StaticResource BaseAnimationsStyle}" />
LuckyLikey
  • 3,504
  • 1
  • 31
  • 54
0

Another Solution:

Create AttachedProperties for Visiblity. This enables you to set the Visibility of any control without having the Opacity set automatically.

If you want to use Bindings on the property, the first evaluation of the binding causes an animation, if the value is not Visibility.Visible. This is why another Property is needed, to specify another Visibility to start.

public static class AnimateableVisibility
{
    public static readonly DependencyProperty VisibilityProperty = DependencyProperty.RegisterAttached(
        "Visibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility), VisibilityPropertyChanged));

    private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var val = (Visibility) e.NewValue;
        // Set StartVisibility to Visible when Visibility is set to Visible
        if (val == Visibility.Visible) 
            d.SetCurrentValue(StartVisibilityProperty, val);
    }


    public static readonly DependencyProperty StartVisibilityProperty = DependencyProperty.RegisterAttached(
        "StartVisibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility)));

    public static Visibility GetVisibility(DependencyObject obj)
    {
        return (Visibility)obj.GetValue(VisibilityProperty);
    }

    public static void SetVisibility(DependencyObject obj, Visibility value)
    {
        obj.SetValue(VisibilityProperty, value);
    }


    public static Visibility GetStartVisibility(DependencyObject obj)
    {
        return (Visibility)obj.GetValue(VisibilityProperty);
    }

    public static void SetStartVisibility(DependencyObject obj, Visibility value)
    {
        obj.SetValue(VisibilityProperty, value);
    }
}

Now you can use those properties as follows:

<Grid>
    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal">
        <Button Margin="5,0,15,0" Padding="7,0" Style="{StaticResource VisibilityAnimation}" utils:AnimateableVisibility.StartVisibility="Hidden"
            utils:AnimateableVisibility.Visibility="{Binding ElementName=CheckBox, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">I'm a Button</Button>
        <CheckBox VerticalAlignment="Center" IsChecked="False" x:Name="CheckBox"></CheckBox>
    </StackPanel>
</Grid>

By changing StartVisibility to Visible, you can see how the Button fades out on startup.

all thats missing now is the applied Style:

<Style x:Key="VisibilityAnimation">
    <Style.Triggers>
        <Trigger Property="utils:AnimateableVisibility.StartVisibility" Value="Hidden">
            <!-- This avoids the Animation in cases when the first evaluation of AnimateableVisibility.Visibility is false -->
            <Setter Property="UIElement.Visibility" Value="Hidden" />
        </Trigger>
        <Trigger Property="utils:AnimateableVisibility.Visibility" Value="Visible">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard TargetProperty="Opacity">
                        <DoubleAnimation To="1" Duration="0:0:2"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard TargetProperty="Opacity">
                        <DoubleAnimation To="0" Duration="0:0:2"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style>
LuckyLikey
  • 3,504
  • 1
  • 31
  • 54