¿Cómo puedo obtener un GIF animado para trabajar en WPF?

¿Qué tipo de control debo usar – Image , MediaElement , etc.?

No pude obtener la respuesta más popular a esta pregunta (anterior por Darío) para que funcione correctamente. El resultado fue una animación extraña y entrecortada con artefactos extraños. La mejor solución que he encontrado hasta ahora: https://github.com/XamlAnimatedGif/WpfAnimatedGif

Puedes instalarlo con NuGet

PM> Install-Package WpfAnimatedGif

y para usarlo, en un nuevo espacio de nombre para la ventana donde desea agregar la imagen gif y usarla como se muestra a continuación

  Title="MainWindow" Height="350" Width="525">    

El paquete es realmente limpio, puedes establecer algunos atributos como a continuación

   

y también puedes usarlo en tu código:

 var image = new BitmapImage(); image.BeginInit(); image.UriSource = new Uri(fileName); image.EndInit(); ImageBehavior.SetAnimatedSource(img, image); 

Publiqué una solución que extiende el control de imagen y usa el decodificador Gif. El decodificador gif tiene una propiedad de marcos. Yo FrameIndex propiedad FrameIndex . El evento ChangingFrameIndex cambia la propiedad de origen al cuadro correspondiente al FrameIndex (que está en el decodificador). Supongo que el gif tiene 10 fotogtwigs por segundo.

 class GifImage : Image { private bool _isInitialized; private GifBitmapDecoder _gifDecoder; private Int32Animation _animation; public int FrameIndex { get { return (int)GetValue(FrameIndexProperty); } set { SetValue(FrameIndexProperty, value); } } private void Initialize() { _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); _animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000)))); _animation.RepeatBehavior = RepeatBehavior.Forever; this.Source = _gifDecoder.Frames[0]; _isInitialized = true; } static GifImage() { VisibilityProperty.OverrideMetadata(typeof (GifImage), new FrameworkPropertyMetadata(VisibilityPropertyChanged)); } private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if ((Visibility)e.NewValue == Visibility.Visible) { ((GifImage)sender).StartAnimation(); } else { ((GifImage)sender).StopAnimation(); } } public static readonly DependencyProperty FrameIndexProperty = DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex))); static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev) { var gifImage = obj as GifImage; gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue]; } ///  /// Defines whether the animation starts on it's own ///  public bool AutoStart { get { return (bool)GetValue(AutoStartProperty); } set { SetValue(AutoStartProperty, value); } } public static readonly DependencyProperty AutoStartProperty = DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged)); private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue) (sender as GifImage).StartAnimation(); } public string GifSource { get { return (string)GetValue(GifSourceProperty); } set { SetValue(GifSourceProperty, value); } } public static readonly DependencyProperty GifSourceProperty = DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged)); private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { (sender as GifImage).Initialize(); } ///  /// Starts the animation ///  public void StartAnimation() { if (!_isInitialized) this.Initialize(); BeginAnimation(FrameIndexProperty, _animation); } ///  /// Stops the animation ///  public void StopAnimation() { BeginAnimation(FrameIndexProperty, null); } } 

Ejemplo de uso (XAML):

  

Yo también hice una búsqueda y encontré varias soluciones diferentes en solo un hilo en los viejos foros de MSDN. (el enlace ya no funciona, así que lo eliminé)

El más simple de ejecutar parece ser el uso de un control WinForms PictureBox , y fue así (se cambiaron algunas cosas del hilo, la mayoría de las mismas).

Agregue primero una referencia a System.Windows.Forms , WindowsFormsIntegration y System.Drawing a su proyecto.

         

Luego, en el controlador Window_Loaded , establecería la propiedad pictureBoxLoading.ImageLocation en la ruta del archivo de imagen que desea mostrar.

 private void Window_Loaded(object sender, RoutedEventArgs e) { pictureBoxLoading.ImageLocation = "../Images/mygif.gif"; } 

El control MediaElement se mencionó en ese hilo, pero también se menciona que es un control bastante pesado, por lo que hubo una serie de alternativas, que incluyen al menos 2 controles elaborados en casa basados ​​en el control de Image , por lo que este es el más simple.

¿Qué tal esta pequeña aplicación? Código detrás:

 public MainWindow() { InitializeComponent(); Files = Directory.GetFiles(@"I:\images"); this.DataContext= this; } public string[] Files {get;set;} 

XAML:

           

Es muy simple si usas :

  

Aquí está mi versión del control de imagen animado. Puede usar la propiedad estándar Fuente para especificar el origen de la imagen. Lo mejoré aún más. Soy un ruso, el proyecto es ruso, por lo que los comentarios también están en ruso. Pero de todas formas deberías poder entender todo sin comentarios. 🙂

 ///  /// Control the "Images", which supports animated GIF. ///  public class AnimatedImage : Image { #region Public properties ///  /// Gets / sets the number of the current frame. ///  public int FrameIndex { get { return (int) GetValue(FrameIndexProperty); } set { SetValue(FrameIndexProperty, value); } } ///  /// Gets / sets the image that will be drawn. ///  public new ImageSource Source { get { return (ImageSource) GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } #endregion #region Protected interface ///  /// Provides derived classes an opportunity to handle changes to the Source property. ///  protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs aEventArgs) { ClearAnimation(); BitmapImage lBitmapImage = aEventArgs.NewValue as BitmapImage; if (lBitmapImage == null) { ImageSource lImageSource = aEventArgs.NewValue as ImageSource; base.Source = lImageSource; return; } if (!IsAnimatedGifImage(lBitmapImage)) { base.Source = lBitmapImage; return; } PrepareAnimation(lBitmapImage); } #endregion #region Private properties private Int32Animation Animation { get; set; } private GifBitmapDecoder Decoder { get; set; } private bool IsAnimationWorking { get; set; } #endregion #region Private methods private void ClearAnimation() { if (Animation != null) { BeginAnimation(FrameIndexProperty, null); } IsAnimationWorking = false; Animation = null; Decoder = null; } private void PrepareAnimation(BitmapImage aBitmapImage) { Debug.Assert(aBitmapImage != null); if (aBitmapImage.UriSource != null) { Decoder = new GifBitmapDecoder( aBitmapImage.UriSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); } else { aBitmapImage.StreamSource.Position = 0; Decoder = new GifBitmapDecoder( aBitmapImage.StreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); } Animation = new Int32Animation( 0, Decoder.Frames.Count - 1, new Duration( new TimeSpan( 0, 0, 0, Decoder.Frames.Count / 10, (int) ((Decoder.Frames.Count / 10.0 - Decoder.Frames.Count / 10) * 1000)))) { RepeatBehavior = RepeatBehavior.Forever }; base.Source = Decoder.Frames[0]; BeginAnimation(FrameIndexProperty, Animation); IsAnimationWorking = true; } private bool IsAnimatedGifImage(BitmapImage aBitmapImage) { Debug.Assert(aBitmapImage != null); bool lResult = false; if (aBitmapImage.UriSource != null) { BitmapDecoder lBitmapDecoder = BitmapDecoder.Create( aBitmapImage.UriSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); lResult = lBitmapDecoder is GifBitmapDecoder; } else if (aBitmapImage.StreamSource != null) { try { long lStreamPosition = aBitmapImage.StreamSource.Position; aBitmapImage.StreamSource.Position = 0; GifBitmapDecoder lBitmapDecoder = new GifBitmapDecoder( aBitmapImage.StreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); lResult = lBitmapDecoder.Frames.Count > 1; aBitmapImage.StreamSource.Position = lStreamPosition; } catch { lResult = false; } } return lResult; } private static void ChangingFrameIndex (DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs) { AnimatedImage lAnimatedImage = aObject as AnimatedImage; if (lAnimatedImage == null || !lAnimatedImage.IsAnimationWorking) { return; } int lFrameIndex = (int) aEventArgs.NewValue; ((Image) lAnimatedImage).Source = lAnimatedImage.Decoder.Frames[lFrameIndex]; lAnimatedImage.InvalidateVisual(); } ///  /// Handles changes to the Source property. ///  private static void OnSourceChanged (DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs) { ((AnimatedImage) aObject).OnSourceChanged(aEventArgs); } #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 (ImageSource), typeof (AnimatedImage), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure, OnSourceChanged)); #endregion } 

Yo uso esta biblioteca: http://wpfanimatedgif.codeplex.com/

Primero, instale la biblioteca en su proyecto (usando la consola del administrador de paquetes):

  PM > Install-Package WpfAnimatedGif 

Luego, usa este fragmento en el archivo XAML:

     ... 

Espero ayuda

Fuente: http://wpfanimatedgif.codeplex.com/

Básicamente, la misma solución PictureBox anterior, pero esta vez con el código subyacente para usar un recurso incrustado en su proyecto:

En XAML:

    

En código subyacente:

 public partial class ProgressIcon { public ProgressIcon() { InitializeComponent(); var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("My.Namespace.ProgressIcon.gif"); var image = System.Drawing.Image.FromStream(stream); Loaded += (s, e) => _loadingPictureBox.Image = image; } } 

Modifiqué el código de Mike Eshva, y lo hice funcionar mejor. Puedes usarlo con 1 fotogtwig jpg png bmp o fotogtwig mutil-frame. Si quieres vincular un uri al control, vincula las propiedades de UriSource o quieres vincular cualquier secuencia de memoria que vincula la propiedad de la Fuente que es una Imagen de Mapa de Bits.

  ///  /// Элемент управления "Изображения", поддерживающий анимированные 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 } 

Este es un control personalizado. Debe crearlo en WPF App Project y eliminar la anulación de plantilla en estilo.

Tuve este problema, hasta que descubrí que en WPF4, puede simular sus propias animaciones de imagen de fotogtwig clave. Primero, divida su animación en una serie de imágenes, titule algo así como “Imagen1.gif”, “Imagen2, gif”, y así sucesivamente. Importe esas imágenes en sus recursos de solución. Supongo que los pones en la ubicación de recursos predeterminada para las imágenes.

Vas a usar el control de Imagen. Use el siguiente código XAML. He eliminado lo no esencial.

                                       

Gracias por su publicación, Joel, me ayudó a resolver la falta de compatibilidad de WPF con los GIF animados. Solo agregué un pequeño código ya que tuve un gran problema con la configuración de la propiedad pictureBoxLoading.Image debido a la api de Winforms.

Tuve que configurar la acción de comstackción de mi imagen animada gif como “Contenido” y el directorio Copiar a salida para “Copiar si es más reciente” o “siempre”. Luego en MainWindow () llamé a este método. El único problema es que cuando traté de deshacerme de la transmisión, me dio un gráfico de sobre rojo en lugar de mi imagen. Tendré que resolver ese problema. Esto eliminó el dolor de cargar un BitmapImage y cambiarlo a Bitmap (que obviamente mató mi animación porque ya no es un gif).

 private void SetupProgressIcon() { Uri uri = new Uri("pack://application:,,,/WPFTest;component/Images/animated_progress_apple.gif"); if (uri != null) { Stream stream = Application.GetContentStream(uri).Stream; imgProgressBox.Image = new System.Drawing.Bitmap(stream); } } 

He intentado todo lo anterior, pero cada uno tiene su brevedad, y gracias a todos ustedes, tengo mi propia GifImage:

  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Controls; using System.Windows; using System.Windows.Media.Imaging; using System.IO; using System.Windows.Threading; namespace IEXM.Components { public class GifImage : Image { #region gif Source, such as "/IEXM;component/Images/Expression/f020.gif" public string GifSource { get { return (string)GetValue(GifSourceProperty); } set { SetValue(GifSourceProperty, value); } } public static readonly DependencyProperty GifSourceProperty = DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(null, GifSourcePropertyChanged)); private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { (sender as GifImage).Initialize(); } #endregion #region control the animate ///  /// Defines whether the animation starts on it's own ///  public bool IsAutoStart { get { return (bool)GetValue(AutoStartProperty); } set { SetValue(AutoStartProperty, value); } } public static readonly DependencyProperty AutoStartProperty = DependencyProperty.Register("IsAutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged)); private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue) (sender as GifImage).StartAnimation(); else (sender as GifImage).StopAnimation(); } #endregion private bool _isInitialized = false; private System.Drawing.Bitmap _bitmap; private BitmapSource _source; [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); private BitmapSource GetSource() { if (_bitmap == null) { _bitmap = new System.Drawing.Bitmap(Application.GetResourceStream( new Uri(GifSource, UriKind.RelativeOrAbsolute)).Stream); } IntPtr handle = IntPtr.Zero; handle = _bitmap.GetHbitmap(); BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); DeleteObject(handle); return bs; } private void Initialize() { // Console.WriteLine("Init: " + GifSource); if (GifSource != null) Source = GetSource(); _isInitialized = true; } private void FrameUpdatedCallback() { System.Drawing.ImageAnimator.UpdateFrames(); if (_source != null) { _source.Freeze(); } _source = GetSource(); // Console.WriteLine("Working: " + GifSource); Source = _source; InvalidateVisual(); } private void OnFrameChanged(object sender, EventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback)); } ///  /// Starts the animation ///  public void StartAnimation() { if (!_isInitialized) this.Initialize(); // Console.WriteLine("Start: " + GifSource); System.Drawing.ImageAnimator.Animate(_bitmap, OnFrameChanged); } ///  /// Stops the animation ///  public void StopAnimation() { _isInitialized = false; if (_bitmap != null) { System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged); _bitmap.Dispose(); _bitmap = null; } _source = null; Initialize(); GC.Collect(); GC.WaitForFullGCComplete(); // Console.WriteLine("Stop: " + GifSource); } public void Dispose() { _isInitialized = false; if (_bitmap != null) { System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged); _bitmap.Dispose(); _bitmap = null; } _source = null; GC.Collect(); GC.WaitForFullGCComplete(); // Console.WriteLine("Dispose: " + GifSource); } } } 

Uso:

  

Como no causaría pérdida de memoria y animó la línea de tiempo de la imagen gif, puedes intentarlo.

Anteriormente, me enfrentaba a un problema similar, necesitaba reproducir el archivo .gif en tu proyecto. Tenía dos opciones:

  • usando PictureBox de WinForms

  • utilizando una biblioteca de terceros, como WPFAnimatedGif de codeplex.com.

La versión con PictureBox no funcionó para mí, y el proyecto no pudo usar bibliotecas externas para ella. Así que lo hice por mí mismo a través de Bitmap con la ayuda de ImageAnimator . Porque, BitmapImage estándar no admite la reproducción de archivos .gif .

Ejemplo completo:

XAML

      

Code behind

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } Bitmap _bitmap; BitmapSource _source; private BitmapSource GetSource() { if (_bitmap == null) { string path = Directory.GetCurrentDirectory(); // Check the path to the .gif file _bitmap = new Bitmap(path + @"\anim.gif"); } IntPtr handle = IntPtr.Zero; handle = _bitmap.GetHbitmap(); return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { _source = GetSource(); SampleImage.Source = _source; ImageAnimator.Animate(_bitmap, OnFrameChanged); } private void FrameUpdatedCallback() { ImageAnimator.UpdateFrames(); if (_source != null) { _source.Freeze(); } _source = GetSource(); SampleImage.Source = _source; InvalidateVisual(); } private void OnFrameChanged(object sender, EventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback)); } } 

Bitmap does not support URI directive, so I load .gif file from the current directory.

Small improvement of GifImage.Initialize() method, which reads proper frame timing from GIF metadata.

  private void Initialize() { _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); int duration=0; _animation = new Int32AnimationUsingKeyFrames(); _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(0, KeyTime.FromTimeSpan(new TimeSpan(0)))); foreach (BitmapFrame frame in _gifDecoder.Frames) { BitmapMetadata btmd = (BitmapMetadata)frame.Metadata; duration += (ushort)btmd.GetQuery("/grctlext/Delay"); _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(_gifDecoder.Frames.IndexOf(frame)+1, KeyTime.FromTimeSpan(new TimeSpan(duration*100000)))); } _animation.RepeatBehavior = RepeatBehavior.Forever; this.Source = _gifDecoder.Frames[0]; _isInitialized = true; } 

I am not sure if this has been solved but the best way is to use the WpfAnimatedGid library . It is very easy, simple and straight forward to use. It only requires 2lines of XAML code and about 5 lines of C# Code in the code behind.

You will see all the necessary details of how this can be used there. This is what I also used instead of re-inventing the wheel

Adding on to the main response that recommends the usage of WpfAnimatedGif , you must add the following lines in the end if you are swapping an image with a Gif to ensure the animation actually executes:

 ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0)); ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever); 

So your code will look like:

 var image = new BitmapImage(); image.BeginInit(); image.UriSource = new Uri(fileName); image.EndInit(); ImageBehavior.SetAnimatedSource(img, image); ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0)); ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);