/// <summary> /// Starts an animation to a particular value on the specified dependency property. /// You can pass in an event handler to call when the animation has completed. /// </summary> public static void StartAnimation(UIElement animatableElement, DependencyProperty dependencyProperty, Visibility toValue, double animationDurationSeconds, EventHandler completedEvent) { ObjectAnimationUsingKeyFrames objanimation = new ObjectAnimationUsingKeyFrames(); DiscreteObjectKeyFrame dobjf = new DiscreteObjectKeyFrame(toValue, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))); objanimation.BeginTime = TimeSpan.FromMilliseconds(0); objanimation.Duration = TimeSpan.FromMilliseconds(animationDurationSeconds); objanimation.KeyFrames = new ObjectKeyFrameCollection() { dobjf }; objanimation.Completed += delegate(object sender, EventArgs e) { // // When the animation has completed bake final value of the animation // into the property. // animatableElement.SetValue(dependencyProperty, animatableElement.GetValue(dependencyProperty)); CancelAnimation(animatableElement, dependencyProperty); if (completedEvent != null) { completedEvent(sender, e); } }; objanimation.Freeze(); objanimation.BeginAnimation(dependencyProperty, objanimation); }
private static void InitAnimationOrImage(Image imageControl) { BitmapSource source = GetAnimatedSource(imageControl) as BitmapSource; bool isInDesignMode = DesignerProperties.GetIsInDesignMode(imageControl); bool animateInDesignMode = GetAnimateInDesignMode(imageControl); bool shouldAnimate = !isInDesignMode || animateInDesignMode; // For a BitmapImage with a relative UriSource, the loading is deferred until // BaseUri is set. This method will be called again when BaseUri is set. bool isLoadingDeferred = IsLoadingDeferred(source); if (source != null && shouldAnimate && !isLoadingDeferred) { GifFile gifMetadata; var decoder = GetDecoder(source, out gifMetadata) as GifBitmapDecoder; if (decoder != null && decoder.Frames.Count > 1) { int index = 0; var animation = new ObjectAnimationUsingKeyFrames(); var totalDuration = TimeSpan.Zero; BitmapSource baseFrame = null; foreach (var rawFrame in decoder.Frames) { var metadata = GetFrameMetadata(decoder, gifMetadata, index); var frame = MakeFrame(source, rawFrame, metadata, baseFrame); var keyFrame = new DiscreteObjectKeyFrame(frame, totalDuration); animation.KeyFrames.Add(keyFrame); totalDuration += metadata.Delay; switch (metadata.DisposalMethod) { case FrameDisposalMethod.None: case FrameDisposalMethod.DoNotDispose: baseFrame = frame; break; case FrameDisposalMethod.RestoreBackground: baseFrame = null; break; case FrameDisposalMethod.RestorePrevious: // Reuse same base frame break; } index++; } animation.Duration = totalDuration; animation.RepeatBehavior = GetActualRepeatBehavior(imageControl, decoder, gifMetadata); animation.Completed += delegate { imageControl.RaiseEvent( new RoutedEventArgs(AnimationCompletedEvent, imageControl)); }; animation.Freeze(); if (animation.KeyFrames.Count > 0) { // For some reason, it sometimes throws an exception the first time... the second time it works. TryTwice(() => imageControl.Source = (ImageSource)animation.KeyFrames[0].Value); } else { imageControl.Source = decoder.Frames[0]; } imageControl.BeginAnimation(Image.SourceProperty, animation); return; } } imageControl.Source = source; }