0

I'm using flipview and bind data. I want to use fadein/out animation when itmes are changed. I'm using DispatcherTimer to change itmes ( _timer.Tick += ChangeImage;).

bind data to flipview

<FlipView x:Name="TheFlipView"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
ItemTemplate="{StaticResource Standard250x250ItemTemplate}"/>

change function.

private void ChangeItems(object sender, object o)
{   
    var totalItems = TheFlipView.Items.Count;
    var newItemIndex = (TheFlipView.SelectedIndex + 1) % totalItems;
    TheFlipView.SelectedIndex = newItemIndex;
}           

I tried Storyboard and FadeInThemeAnimation class, but I couldn't ...

Could you help me?

hiroo
  • 657
  • 2
  • 7
  • 13

2 Answers2

3

Here's a class from WinRT XAML Toolkit that you can use to fade in/fade out with simple calls like myFlipView.FadeOut(). You could just change your code to something like this:

private async void ChangeItems(object sender, object o)
{   
    var totalItems = TheFlipView.Items.Count;
    var newItemIndex = (TheFlipView.SelectedIndex + 1) % totalItems;
    await TheFlipView.FadeOut();
    TheFlipView.SelectedIndex = newItemIndex;
    TheFlipView.FadeIn();
}     

Extensions class:

public static class UIElementAnimationExtensions
{
    #region AttachedFadeStoryboard
    /// <summary>
    /// AttachedFadeStoryboard Attached Dependency Property
    /// </summary>
    public static readonly DependencyProperty AttachedFadeStoryboardProperty =
        DependencyProperty.RegisterAttached(
            "AttachedFadeStoryboard",
            typeof(Storyboard),
            typeof(UIElementAnimationExtensions),
            new PropertyMetadata(null, OnAttachedFadeStoryboardChanged));

    /// <summary>
    /// Gets the AttachedFadeStoryboard property. This dependency property 
    /// indicates the currently running custom fade in/out storyboard.
    /// </summary>
    private static Storyboard GetAttachedFadeStoryboard(DependencyObject d)
    {
        return (Storyboard)d.GetValue(AttachedFadeStoryboardProperty);
    }

    /// <summary>
    /// Sets the AttachedFadeStoryboard property. This dependency property 
    /// indicates the currently running custom fade in/out storyboard.
    /// </summary>
    private static void SetAttachedFadeStoryboard(DependencyObject d, Storyboard value)
    {
        d.SetValue(AttachedFadeStoryboardProperty, value);
    }

    /// <summary>
    /// Handles changes to the AttachedFadeStoryboard property.
    /// </summary>
    /// <param name="d">
    /// The <see cref="DependencyObject"/> on which
    /// the property has changed value.
    /// </param>
    /// <param name="e">
    /// Event data that is issued by any event that
    /// tracks changes to the effective value of this property.
    /// </param>
    private static void OnAttachedFadeStoryboardChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Storyboard oldAttachedFadeStoryboard = (Storyboard)e.OldValue;
        Storyboard newAttachedFadeStoryboard = (Storyboard)d.GetValue(AttachedFadeStoryboardProperty);
    }
    #endregion

    #region FadeIn()
    /// <summary>
    /// Fades the element in using the FadeInThemeAnimation.
    /// </summary>
    /// <remarks>
    /// Opacity property of the element is not affected.<br/>
    /// The duration of the visible animation itself is not affected by the duration parameter. It merely indicates how long the Storyboard will run.<br/>
    /// If FadeOutThemeAnimation was not used on the element before - nothing will happen.<br/>
    /// </remarks>
    /// <param name="element"></param>
    /// <param name="duration"></param>
    /// <returns></returns>
    public static async Task FadeIn(this UIElement element, TimeSpan? duration = null)
    {
        ((FrameworkElement)element).Visibility = Visibility.Visible;
        var fadeInStoryboard = new Storyboard();
        var fadeInAnimation = new FadeInThemeAnimation();

        if (duration != null)
        {
            fadeInAnimation.Duration = duration.Value;
        }

        Storyboard.SetTarget(fadeInAnimation, element);
        fadeInStoryboard.Children.Add(fadeInAnimation);
        await fadeInStoryboard.BeginAsync();
    } 
    #endregion

    #region FadeOut()
    /// <summary>
    /// Fades the element out using the FadeOutThemeAnimation.
    /// </summary>
    /// <remarks>
    /// Opacity property of the element is not affected.<br/>
    /// The duration of the visible animation itself is not affected by the duration parameter. It merely indicates how long the Storyboard will run.<br/>
    /// If FadeOutThemeAnimation was already run before and FadeInThemeAnimation was not run after that - nothing will happen.<br/>
    /// </remarks>
    /// <param name="element"></param>
    /// <param name="duration"></param>
    /// <returns></returns>
    public static async Task FadeOut(this UIElement element, TimeSpan? duration = null)
    {
        var fadeOutStoryboard = new Storyboard();
        var fadeOutAnimation = new FadeOutThemeAnimation();

        if (duration != null)
        {
            fadeOutAnimation.Duration = duration.Value;
        }

        Storyboard.SetTarget(fadeOutAnimation, element);
        fadeOutStoryboard.Children.Add(fadeOutAnimation);
        await fadeOutStoryboard.BeginAsync();
    } 
    #endregion

    #region FadeInCustom()
    /// <summary>
    /// Fades the element in using a custom DoubleAnimation of the Opacity property.
    /// </summary>
    /// <param name="element"></param>
    /// <param name="duration"></param>
    /// <param name="easingFunction"> </param>
    /// <returns></returns>
    public static async Task FadeInCustom(this UIElement element, TimeSpan? duration = null, EasingFunctionBase easingFunction = null, double targetOpacity = 1.0)
    {
        CleanUpPreviousFadeStoryboard(element);

        var fadeInStoryboard = new Storyboard();
        var fadeInAnimation = new DoubleAnimation();

        if (duration == null)
            duration = TimeSpan.FromSeconds(0.4);

        fadeInAnimation.Duration = duration.Value;
        fadeInAnimation.To = targetOpacity;
        fadeInAnimation.EasingFunction = easingFunction;

        Storyboard.SetTarget(fadeInAnimation, element);
        Storyboard.SetTargetProperty(fadeInAnimation, "Opacity");
        fadeInStoryboard.Children.Add(fadeInAnimation);
        SetAttachedFadeStoryboard(element, fadeInStoryboard);
        await fadeInStoryboard.BeginAsync();
        element.Opacity = targetOpacity;
        fadeInStoryboard.Stop();
    }
    #endregion

    #region FadeOutCustom()
    /// <summary>
    /// Fades the element out using a custom DoubleAnimation of the Opacity property.
    /// </summary>
    /// <param name="element"></param>
    /// <param name="duration"></param>
    /// <param name="easingFunction"> </param>
    /// <returns></returns>
    public static async Task FadeOutCustom(this UIElement element, TimeSpan? duration = null, EasingFunctionBase easingFunction = null)
    {
        CleanUpPreviousFadeStoryboard(element); 

        var fadeOutStoryboard = new Storyboard();
        var fadeOutAnimation = new DoubleAnimation();

        if (duration == null)
            duration = TimeSpan.FromSeconds(0.4);

        fadeOutAnimation.Duration = duration.Value;
        fadeOutAnimation.To = 0.0;
        fadeOutAnimation.EasingFunction = easingFunction;

        Storyboard.SetTarget(fadeOutAnimation, element);
        Storyboard.SetTargetProperty(fadeOutAnimation, "Opacity");
        fadeOutStoryboard.Children.Add(fadeOutAnimation);
        SetAttachedFadeStoryboard(element, fadeOutStoryboard);
        await fadeOutStoryboard.BeginAsync();
        element.Opacity = 0.0;
        fadeOutStoryboard.Stop();
    } 
    #endregion

    #region CleanUpPreviousFadeStoryboard()
    public static void CleanUpPreviousFadeStoryboard(this UIElement element)
    {
        var attachedFadeStoryboard = GetAttachedFadeStoryboard(element);

        if (attachedFadeStoryboard != null)
        {
            attachedFadeStoryboard.Stop();
        }
    }
    #endregion
}
Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
0

The goal of this answer is to complement Filip Skakun's answer since the extension BeginAsync was missed. After embedding this extension as shown below into his class UIElementAnimationExtensions, it works fine for my case. ^_^

    public async static Task BeginAsync(this Storyboard myStoryboard)
    {
        SemaphoreSlim signal = new SemaphoreSlim(0, 1);
        EventHandler<object> eventHandler = new EventHandler<object>(
            (sender, args) => 
            {
                signal.Release();
            }
            );
        myStoryboard.Completed += eventHandler;
        myStoryboard.Begin();
        await signal.WaitAsync();
        myStoryboard.Completed -= eventHandler;
    }

By the way, the concept of this extension is based on the answer of Is it possible to await an event instead of another async method?.

Community
  • 1
  • 1