Come faccio a ottenere una gif animata per funzionare in WPF?

Quale tipo di controllo dovrei usare: Image , MediaElement , ecc.?

Non ho potuto ottenere la risposta più popolare a questa domanda (sopra Dario) per funzionare correttamente. Il risultato è stato un’animazione strana e irregolare con strani artefatti. La migliore soluzione che ho trovato finora: https://github.com/XamlAnimatedGif/WpfAnimatedGif

Puoi installarlo con NuGet

PM> Install-Package WpfAnimatedGif

e usarlo, in un nuovo spazio dei nomi della Finestra in cui si desidera aggiungere l’immagine GIF e usarlo come sotto

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

Il pacchetto è davvero pulito, puoi impostare alcuni attributi come di seguito

   

e puoi usarlo anche nel tuo codice:

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

Inserisco una soluzione estendendo il controllo dell’immagine e utilizzando il Decoder Gif. Il decodificatore gif ha una proprietà frames. FrameIndex proprietà FrameIndex . L’evento ChangingFrameIndex cambia la proprietà sorgente nel frame corrispondente al FrameIndex (che si trova nel decodificatore). Immagino che la gif abbia 10 fotogrammi al secondo.

 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); } } 

Esempio di utilizzo (XAML):

  

Anch’io ho fatto una ricerca e ho trovato diverse soluzioni in una discussione sui vecchi forum MSDN. (il collegamento non funzionava più, quindi l’ho rimosso)

Il più semplice da eseguire sembra essere quello di utilizzare un controllo PictureBox WinForms, e ha funzionato in questo modo (ha cambiato alcune cose dal thread, quasi sempre lo stesso).

Aggiungere un riferimento a System.Windows.Forms , WindowsFormsIntegration e System.Drawing al progetto prima.

         

Quindi, nel gestore Window_Loaded , si imposta la proprietà pictureBoxLoading.ImageLocation sul percorso del file immagine che si desidera mostrare.

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

Il controllo MediaElement stato menzionato in quel thread, ma si dice anche che è un controllo piuttosto pesante, quindi c’erano un certo numero di alternative, inclusi almeno 2 controlli homebrewed basati sul controllo Image , quindi questo è il più semplice.

Che ne dici di questa piccola app: Codice dietro:

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

XAML:

           

È molto semplice se usi :

  

Ecco la mia versione del controllo dell’immagine animata. È ansible utilizzare la fonte di proprietà standard per specificare l’origine dell’immagine. L’ho ulteriormente migliorato. Sono russo, il progetto è russo quindi anche i commenti sono in russo. Ma comunque dovresti essere in grado di capire tutto senza commenti. 🙂

 ///  /// 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 classs 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 } 

Io uso questa libreria: http://wpfanimatedgif.codeplex.com/

Innanzitutto, installa la libreria nel progetto (utilizzando la console di Package Manager):

  PM > Install-Package WpfAnimatedGif 

Quindi, utilizza questo snippet nel file XAML:

     ... 

Spero che aiuti.

Fonte: http://wpfanimatedgif.codeplex.com/

Fondamentalmente la stessa soluzione PictureBox sopra, ma questa volta con il codice sottostante per utilizzare una risorsa incorporata nel progetto:

In XAML:

    

In Code-Behind:

 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; } } 

Ho modificato il codice di Mike Eshva, e l’ho fatto funzionare meglio. Puoi usarlo sia con 1frame jpg png bmp o con gif mutil-frame. Se vuoi associare un uri al controllo, bind le proprietà UriSource o vuoi associare stream di memoria che si associa alla proprietà di origine che è un 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 classs 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 } 

Questo è un controllo personalizzato. È necessario crearlo in WPF App Project ed eliminare il modello Override in stile.

Ho avuto questo problema, fino a quando ho scoperto che in WPF4, puoi simulare le tue animazioni di immagini dei fotogrammi chiave. Per prima cosa, dividi l’animazione in una serie di immagini, intitolandole qualcosa come “Image1.gif”, “Immagine2, gif” e così via. Importa queste immagini nelle risorse della tua soluzione. Suppongo che tu li abbia inseriti nella posizione predefinita delle risorse per le immagini.

Stai per usare il controllo Immagine. Utilizza il seguente codice XAML. Ho rimosso i non essenziali.

                                       

Grazie per il tuo post Joel, mi ha aiutato a risolvere l’assenza di supporto di WPF per le GIF animate. Aggiungendo solo un piccolo codice da quando ho avuto un po ‘di tempo con l’impostazione della proprietà pictureBoxLoading.Image a causa dell’API Winforms.

Ho dovuto impostare l’azione di animazione dell’immagine gif animata come “Contenuto” e la directory Copia in uscita su “Copia se più recente” o “sempre”. Quindi nel MainWindow () ho chiamato questo metodo. L’unico problema è che quando ho provato a smaltire il stream, mi ha dato una grafica a busta rossa al posto della mia immagine. Dovrò risolvere questo problema. Ciò ha rimosso il dolore di caricare un BitmapImage e di modificarlo in un Bitmap (che ovviamente ha ucciso la mia animazione perché non è più una 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); } } 

Ho provato fino in fondo, ma ognuno ha la sua brevità, e grazie a tutti voi, mi dedico alla mia 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:

  

Poiché non causerebbe perdita di memoria e ha animato la sequenza temporale dell’immagine GIF, puoi provarla.

Precedentemente, ho affrontato un problema simile, avevo bisogno di riprodurre il file .gif nel tuo progetto. Ho avuto due scelte:

  • usando PictureBox da WinForms

  • utilizzando una libreria di terze parti, come WPFAnimatedGif da codeplex.com.

La versione con PictureBox non funzionava per me e il progetto non poteva usare librerie esterne per questo. Così l’ho creato da solo tramite Bitmap con l’aiuto di ImageAnimator . Perché, BitmapImage standard non supporta la riproduzione di file .gif .

Esempio 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);