简体   繁体   English

在WPF中显示GIF动画图像的最佳方法是什么?

[英]What's the best way for displaying GIF Animation Images in WPF?

I would like to display an animation gif such as loading... in my XAML as my procedure is progressing. 我希望在我的XAML中显示动画gif,例如loading ...,因为我的程序正在进行中。 I found out that this cannot be easily done in WPF as I loaded my Gif and it just shows the first frame. 我发现这在WPF中不能轻易完成,因为我加载了我的Gif并且它只显示了第一帧。 What are the best ways to display an animation in WPF. 在WPF中显示动画的最佳方法是什么?

You can use the following code for loading GIFImage in a WPF app 您可以使用以下代码在WPF应用程序中加载GIFImage

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;

    /// <summary>
    /// Class to host nornmal and Gif images and plays the animation.
    /// To make it work, instead of setting ImageSource, set the AnimationSourcePath property.
    /// </summary>
    public class GifImage : Image
    {
        /// <summary>
        /// Dependency property to hold value for AnimationSourcePath.
        /// </summary>
        public static readonly DependencyProperty AnimationSourcePathProperty =
            DependencyProperty.Register(
            "AnimationSourcePath",
            typeof(string),
            typeof(GifImage),
            new UIPropertyMetadata(String.Empty, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Dependency property to hold value of integer animation timeline values for FrameIndex.
        /// </summary>
        private static readonly DependencyProperty FrameIndexProperty =
            DependencyProperty.Register(
            "FrameIndex",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));

        /// <summary>
        /// Dependency property to hold value of integer animation rate which slows down animation speed if value is more than 1.
        /// </summary>
        private static readonly DependencyProperty FrameRefreshRateProperty =
            DependencyProperty.Register(
            "FrameRefreshRate",
            typeof(int),
            typeof(GifImage),
            new UIPropertyMetadata(1, AnimationSourcePathPropertyChanged));

        /// <summary>
        /// Member to hold animation timeline for integer values.
        /// </summary>
        private Int32Animation anim;

        /// <summary>
        /// Member to hold flag to indicate if animation is working.
        /// </summary>
        private bool animationIsWorking = false;

        /// <summary>
        /// Member to hold Gif Bitmap Decoder.
        /// </summary>
        private GifBitmapDecoder gf;

        /// <summary>
        /// Initializes a new instance of the GifImage class.
        /// </summary>
        public GifImage()
        {
        }

        /// <summary>
        /// Initializes a new instance of the GifImage class based on the uri.
        /// </summary>
        /// <param name="uri">Uri of the image source.</param>
        public GifImage(Uri uri)
        {
            GifImage.SetupAnimationSource(this, uri);
        }

        /// <summary>
        /// Gets or sets a value indicating AnimationSourcePath.
        /// </summary>
        public string AnimationSourcePath
        {
            get { return (string)GetValue(AnimationSourcePathProperty); }
            set { SetValue(AnimationSourcePathProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value indicating FrameIndex.
        /// </summary>
        public int FrameIndex
        {
            get { return (int)GetValue(FrameIndexProperty); }
            set { SetValue(FrameIndexProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value for frame refresh rate. A value more than 1 would slow the animation down.
        /// </summary>
        public int FrameRefreshRate
        {
            get { return (int)GetValue(FrameRefreshRateProperty); }
            set { SetValue(FrameRefreshRateProperty, value); }
        }

        /// <summary>
        /// Method to handle property changed event of AnimationSourcePath property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void AnimationSourcePathPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.BeginAnimation(GifImage.FrameIndexProperty, null);
            ob.anim = null;
            ob.gf = null;
            ob.Source = null;

            if (!String.IsNullOrEmpty(ob.AnimationSourcePath) &&
                Uri.IsWellFormedUriString(ob.AnimationSourcePath, UriKind.RelativeOrAbsolute))
            {
                if (((string)ob.AnimationSourcePath).ToLower().EndsWith(".gif"))
                {
                    Uri uri = new Uri(ob.AnimationSourcePath);
                    GifImage.SetupAnimationSource(ob, uri);
                    ob.BeginAnimation(GifImage.FrameIndexProperty, ob.anim);
                }
                else
                {
                    ob.Source = (new ImageSourceConverter()).ConvertFromString(ob.AnimationSourcePath) as ImageSource;
                    ob.InvalidateVisual();
                }

                ob.animationIsWorking = true;
            }
        }

        /// <summary>
        /// Method to handle property changed event of FrameIndex property.
        /// </summary>
        /// <param name="obj">Source image.</param>
        /// <param name="ev">Event arguments.</param>
        protected static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
        {
            GifImage ob = obj as GifImage;
            ob.Source = ob.gf.Frames[ob.FrameIndex];
            ob.InvalidateVisual();
        }

        /// <summary>
        /// Method to setup animation source against a Gif Image.
        /// </summary>
        /// <param name="ob">Gif image.</param>
        /// <param name="uri">Uri of the gif image source.</param>
        protected static void SetupAnimationSource(GifImage ob, Uri uri)
        {
            ob.gf = new GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            double val = (ob.gf.Frames.Count / 15.0) - (ob.gf.Frames.Count / 15);
            TimeSpan tmpSpn = new TimeSpan(0, 0, 0, ob.gf.Frames.Count / 15, (int)(val * 1000));
            Duration durtn = new Duration(new TimeSpan(tmpSpn.Ticks * ob.FrameRefreshRate));
            ob.anim = new Int32Animation(0, ob.gf.Frames.Count - 1, durtn);
            ob.anim.RepeatBehavior = RepeatBehavior.Forever;
            ob.Source = ob.gf.Frames[0];
        }

        /// <summary>
        /// Method to override the OnRender event of the image.
        /// </summary>
        /// <param name="dc">Drawing Context of the image.</param>
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            if (!this.animationIsWorking)
            {
                BeginAnimation(GifImage.FrameIndexProperty, this.anim);
                this.animationIsWorking = true;
            }
        }
    }

The way you use it as follows.... 您使用它的方式如下....

    <ns:GifImage AnimationSourcePath="../MyGifImage.gif" />

Let me know if this helps you. 如果这有助于您,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM