How do I get an animated gif to work in WPF?

前端 未结 18 1133
广开言路
广开言路 2020-11-22 12:16

What control type should I use - Image, MediaElement, etc.?

18条回答
  •  暖寄归人
    2020-11-22 12:42

    I modified Mike Eshva's code,And I made it work better.You can use it with either 1frame jpg png bmp or mutil-frame gif.If you want bind a uri to the control,bind the UriSource properties or you want bind any in-memory stream that you bind the Source propertie which is a BitmapImage.

        ///  
    /// Элемент управления "Изображения", поддерживающий анимированные GIF. 
    ///  
    public class AnimatedImage : Image
    {
        static AnimatedImage()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage)));
        }
    
        #region Public properties
    
        ///  
        /// Получает/устанавливает номер текущего кадра. 
        ///  
        public int FrameIndex
        {
            get { return (int)GetValue(FrameIndexProperty); }
            set { SetValue(FrameIndexProperty, value); }
        }
    
        /// 
        /// Get the BitmapFrame List.
        /// 
        public List Frames { get; private set; }
    
        /// 
        /// Get or set the repeatBehavior of the animation when source is gif formart.This is a dependency object.
        /// 
        public RepeatBehavior AnimationRepeatBehavior
        {
            get { return (RepeatBehavior)GetValue(AnimationRepeatBehaviorProperty); }
            set { SetValue(AnimationRepeatBehaviorProperty, value); }
        }
    
        public new BitmapImage Source
        {
            get { return (BitmapImage)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }
    
        public Uri UriSource
        {
            get { return (Uri)GetValue(UriSourceProperty); }
            set { SetValue(UriSourceProperty, value); }
        }
    
        #endregion
    
        #region Protected interface
    
        ///  
        /// Provides derived classes an opportunity to handle changes to the Source property. 
        ///  
        protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e)
        {
            ClearAnimation();
            BitmapImage source;
            if (e.NewValue is Uri)
            {
                source = new BitmapImage();
                source.BeginInit();
                source.UriSource = e.NewValue as Uri;
                source.CacheOption = BitmapCacheOption.OnLoad;
                source.EndInit();
            }
            else if (e.NewValue is BitmapImage)
            {
                source = e.NewValue as BitmapImage;
            }
            else
            {
                return;
            }
            BitmapDecoder decoder;
            if (source.StreamSource != null)
            {
                decoder = BitmapDecoder.Create(source.StreamSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
            }
            else if (source.UriSource != null)
            {
                decoder = BitmapDecoder.Create(source.UriSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
            }
            else
            {
                return;
            }
            if (decoder.Frames.Count == 1)
            {
                base.Source = decoder.Frames[0];
                return;
            }
    
            this.Frames = decoder.Frames.ToList();
    
            PrepareAnimation();
        }
    
        #endregion
    
        #region Private properties
    
        private Int32Animation Animation { get; set; }
        private bool IsAnimationWorking { get; set; }
    
        #endregion
    
        #region Private methods
    
        private void ClearAnimation()
        {
            if (Animation != null)
            {
                BeginAnimation(FrameIndexProperty, null);
            }
    
            IsAnimationWorking = false;
            Animation = null;
            this.Frames = null;
        }
    
        private void PrepareAnimation()
        {
            Animation =
                new Int32Animation(
                    0,
                    this.Frames.Count - 1,
                    new Duration(
                        new TimeSpan(
                            0,
                            0,
                            0,
                            this.Frames.Count / 10,
                            (int)((this.Frames.Count / 10.0 - this.Frames.Count / 10) * 1000))))
                {
                    RepeatBehavior = RepeatBehavior.Forever
                };
    
            base.Source = this.Frames[0];
            BeginAnimation(FrameIndexProperty, Animation);
            IsAnimationWorking = true;
        }
    
        private static void ChangingFrameIndex
            (DependencyObject dp, DependencyPropertyChangedEventArgs e)
        {
            AnimatedImage animatedImage = dp as AnimatedImage;
    
            if (animatedImage == null || !animatedImage.IsAnimationWorking)
            {
                return;
            }
    
            int frameIndex = (int)e.NewValue;
            ((Image)animatedImage).Source = animatedImage.Frames[frameIndex];
            animatedImage.InvalidateVisual();
        }
    
        ///  
        /// Handles changes to the Source property. 
        ///  
        private static void OnSourceChanged
            (DependencyObject dp, DependencyPropertyChangedEventArgs e)
        {
            ((AnimatedImage)dp).OnSourceChanged(e);
        }
    
        #endregion
    
        #region Dependency Properties
    
        ///  
        /// FrameIndex Dependency Property 
        ///  
        public static readonly DependencyProperty FrameIndexProperty =
            DependencyProperty.Register(
                "FrameIndex",
                typeof(int),
                typeof(AnimatedImage),
                new UIPropertyMetadata(0, ChangingFrameIndex));
    
        ///  
        /// Source Dependency Property 
        ///  
        public new static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register(
                "Source",
                typeof(BitmapImage),
                typeof(AnimatedImage),
                new FrameworkPropertyMetadata(
                    null,
                    FrameworkPropertyMetadataOptions.AffectsRender |
                    FrameworkPropertyMetadataOptions.AffectsMeasure,
                    OnSourceChanged));
    
        /// 
        /// AnimationRepeatBehavior Dependency Property
        /// 
        public static readonly DependencyProperty AnimationRepeatBehaviorProperty =
            DependencyProperty.Register(
            "AnimationRepeatBehavior",
            typeof(RepeatBehavior),
            typeof(AnimatedImage),
            new PropertyMetadata(null));
    
        public static readonly DependencyProperty UriSourceProperty =
            DependencyProperty.Register(
            "UriSource",
            typeof(Uri),
            typeof(AnimatedImage),
                    new FrameworkPropertyMetadata(
                    null,
                    FrameworkPropertyMetadataOptions.AffectsRender |
                    FrameworkPropertyMetadataOptions.AffectsMeasure,
                    OnSourceChanged));
    
        #endregion
    }
    

    This is a custom control. You need to create it in WPF App Project,and delete the Template override in style.

提交回复
热议问题