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