WPF
animated gif
image animation
software development
user interface

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

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

WPF can display GIF files, but the built-in Image control only shows the first frame by default. If you want real animation, you need to decode the frames yourself or use a helper library that does it for you.

Why a Normal Image Stays Static

WPF image rendering is built around BitmapSource, and a GIF is treated as an image resource rather than a self-playing animation timeline. That is why this code shows the GIF but does not animate it:

xaml
<Image Source="spinner.gif" Width="120" Height="120" />

Nothing is wrong with the file. WPF simply does not advance the GIF frames automatically. To animate it, you need to read the frames, extract each frame delay, and apply an ObjectAnimationUsingKeyFrames to the Image.Source property.

A Dependency-Free WPF Solution

The example below uses only built-in WPF APIs. It works in a standard WPF project as long as spinner.gif is included in the output folder or accessible through the provided URI.

xaml
1<Window x:Class="GifDemo.MainWindow"
2        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4        Title="GIF Demo" Height="220" Width="240">
5    <Grid>
6        <Image x:Name="AnimatedImage" Width="160" Height="160" />
7    </Grid>
8</Window>
csharp
1using System;
2using System.Windows;
3using System.Windows.Controls;
4using System.Windows.Media.Animation;
5using System.Windows.Media.Imaging;
6
7namespace GifDemo;
8
9public partial class MainWindow : Window
10{
11    public MainWindow()
12    {
13        InitializeComponent();
14        PlayGif("spinner.gif");
15    }
16
17    private void PlayGif(string relativePath)
18    {
19        var uri = new Uri(relativePath, UriKind.Relative);
20        var decoder = new GifBitmapDecoder(
21            uri,
22            BitmapCreateOptions.PreservePixelFormat,
23            BitmapCacheOption.Default);
24
25        var animation = new ObjectAnimationUsingKeyFrames();
26        TimeSpan currentTime = TimeSpan.Zero;
27
28        foreach (BitmapFrame frame in decoder.Frames)
29        {
30            ushort delay = 10;
31            if (frame.Metadata is BitmapMetadata metadata && metadata.ContainsQuery("/grctlext/Delay"))
32            {
33                delay = (ushort)metadata.GetQuery("/grctlext/Delay");
34            }
35
36            animation.KeyFrames.Add(
37                new DiscreteObjectKeyFrame(frame, KeyTime.FromTimeSpan(currentTime)));
38
39            currentTime += TimeSpan.FromMilliseconds(Math.Max(1, delay) * 10);
40        }
41
42        animation.Duration = currentTime;
43        animation.RepeatBehavior = RepeatBehavior.Forever;
44
45        AnimatedImage.BeginAnimation(Image.SourceProperty, animation);
46    }
47}

GIF frame delays are stored in hundredths of a second, which is why the example multiplies the delay by 10 milliseconds. The code also defaults to a small delay when the metadata is missing so the animation still plays.

When to Use a Library Instead

If your application shows many animated GIFs or needs simple XAML-only usage, a library can save time. The main benefit is convenience: you bind to a GIF source and let the library manage frame timing and rendering details.

The tradeoff is one more dependency. For a single spinner or status indicator, the built-in frame-decoding approach is often enough. For a UI that uses many animations, a library can make the markup cleaner and the behavior more reusable. It also reduces the chance that every window in the application ends up reimplementing slightly different GIF timing logic.

Common Pitfalls

  • Expecting <Image Source="file.gif" /> to animate by itself. WPF only shows the first frame by default.
  • Giving the decoder a path that is not copied to the output directory or not packaged as a reachable resource.
  • Ignoring GIF frame delay metadata and then wondering why the animation speed looks wrong.
  • Animating a very large GIF in a busy UI thread, which can increase CPU use noticeably.
  • Forgetting that a loading spinner can often be replaced by a vector animation or progress indicator that scales better than a GIF.

Summary

  • WPF does not automatically animate GIF frames in the standard Image control.
  • A working built-in solution uses GifBitmapDecoder plus ObjectAnimationUsingKeyFrames.
  • Frame delays need to be read from GIF metadata so the playback timing is correct.
  • Helper libraries are convenient when your app uses many animated GIFs.
  • For simple indicators, a custom WPF animation may be a better long-term choice than a GIF.

Course illustration
Course illustration

All Rights Reserved.