vladeck's junkyard

designer wannabe

Animated Height Behavior

on September 22, 2010

On one project that I’m working on, I had a need to animate height (simulating Visible/Not Visible state of ‘overlay’ and edit dialogs) of FrameworkElement. So I wrote this little behavior that does just that. You can use IsVisible to control (using binding) ‘Visibility’, as well as ShowDuration and HideDuration to control duration of animation.

using System;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media.Animation;

namespace Foo
{
    public class AnimatedHeightBehavior : Behavior<FrameworkElement>
    {
        private static DoubleAnimation showAnimation_;
        private static readonly Storyboard showStoryboard_ = new Storyboard();

        private static DoubleAnimation hideAnimation_;
        private static readonly Storyboard hideStoryboard_ = new Storyboard();

        public static DependencyProperty IsVisibleProperty =
            DependencyProperty.Register(
                "IsVisible",
                typeof(bool),
                typeof(AnimatedHeightBehavior),
                new PropertyMetadata(false, OnShowChanged)
            );

        public static DependencyProperty ShowDurationProperty =
            DependencyProperty.Register(
                "ShowDuration",
                typeof(int),
                typeof(AnimatedHeightBehavior),
                new PropertyMetadata(200)
        );

        public static DependencyProperty HideDurationProperty =
            DependencyProperty.Register(
                "HideDuration",
                typeof(int),
                typeof(AnimatedHeightBehavior),
                new PropertyMetadata(50)
        );

        public bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
            set { SetValue(IsVisibleProperty, value); }
        }

        public int ShowDuration
        {
            get { return (int)GetValue(HideDurationProperty); }
            set { SetValue(HideDurationProperty, value); }
        }

        public int HideDuration
        {
            get { return (int)GetValue(ShowDurationProperty); }
            set { SetValue(ShowDurationProperty, value); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += OnLoaded;
        }

        protected override void OnDetaching()
        {
            AssociatedObject.Loaded -= OnLoaded;
            base.OnDetaching();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (!IsVisible)
                AssociatedObject.Height = 0.0;

            showAnimation_ = new DoubleAnimation(
                0.0,
                AssociatedObject.ActualHeight,
                TimeSpan.FromMilliseconds((int)GetValue(ShowDurationProperty))
            );

            showAnimation_.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };

            Storyboard.SetTarget(showAnimation_, AssociatedObject);
            Storyboard.SetTargetProperty(showAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
            showStoryboard_.Children.Add(showAnimation_);

            hideAnimation_ = new DoubleAnimation(
                AssociatedObject.ActualHeight,
                0.0,
                TimeSpan.FromMilliseconds((int)GetValue(HideDurationProperty))
            );

            Storyboard.SetTarget(hideAnimation_, AssociatedObject);
            Storyboard.SetTargetProperty(hideAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
            hideStoryboard_.Children.Add(hideAnimation_);
        }

        private static void OnShowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = ((AnimatedHeightBehavior)d).AssociatedObject;

            if ((bool)e.NewValue)
                showStoryboard_.Begin(element);
            else
                hideStoryboard_.Begin(element);
        }
    }
}

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.