Вот мой код:
Код: Выделить всё
public class Gif : Image
{
private bool _isInitialized;
private GifBitmapDecoder _decoder;
private int _frameIndex = 0;
private DispatcherTimer _timer;
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register(nameof(GifSource), typeof(string), typeof(Gif),
new PropertyMetadata(string.Empty, OnGifSourceChanged));
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register(nameof(AutoStart), typeof(bool), typeof(Gif),
new PropertyMetadata(true, OnAutoStartChanged));
public string GifSource
{
get { return (string)GetValue(GifSourceProperty); }
set { SetValue(GifSourceProperty, value); }
}
public bool AutoStart
{
get { return (bool)GetValue(AutoStartProperty); }
set { SetValue(AutoStartProperty, value); }
}
private static void OnGifSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Gif)d).Initialize();
}
private static void OnAutoStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var gif = (Gif)d;
if ((bool)e.NewValue && gif.Visibility == Visibility.Visible)
{
gif.StartAnimation();
}
}
static Gif()
{
VisibilityProperty.OverrideMetadata(typeof(Gif), new FrameworkPropertyMetadata(VisibilityPropertyChanged));
}
private void Initialize()
{
if (string.IsNullOrEmpty(GifSource))
return;
_decoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
this.Source = _decoder.Frames[0];
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.HighQuality);
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
_isInitialized = true;
if (AutoStart && this.Visibility == Visibility.Visible)
StartAnimation();
}
private void StartTimerForFrame(int frameIndex)
{
int delay = 100; // default
try
{
var metadata = _decoder.Frames[frameIndex].Metadata as BitmapMetadata;
if (metadata != null)
{
object delayObj = metadata.GetQuery("/grctlext/Delay");
if (delayObj != null)
delay = ((ushort)delayObj) * 10; // 1/100s → ms
}
}
catch { }
_timer.Interval = TimeSpan.FromMilliseconds(delay);
_timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
if (_decoder == null || _decoder.Frames.Count == 0)
return;
var frame = _decoder.Frames[_frameIndex];
var rtb = new RenderTargetBitmap(frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, System.Windows.Media.PixelFormats.Pbgra32);
var dv = new DrawingVisual();
using (var ctx = dv.RenderOpen())
{
ctx.DrawImage(frame, new Rect(0, 0, frame.PixelWidth, frame.PixelHeight));
}
rtb.Render(dv);
this.Source = rtb;
_frameIndex = (_frameIndex + 1) % _decoder.Frames.Count;
StartTimerForFrame(_frameIndex);
}
private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var gif = (Gif)d;
if ((Visibility)e.NewValue == Visibility.Visible)
gif.StartAnimation();
else
gif.StopAnimation();
}
public void StartAnimation()
{
if (!_isInitialized)
Initialize();
GifAnimation(true);
}
public void StopAnimation()
{
GifAnimation(false);
}
private void GifAnimation(bool toStart)
{
if (_timer == null)
return;
if (toStart)
{
_frameIndex = 0;
StartTimerForFrame(_frameIndex);
}
else
{
_timer.Stop();
}
}
protected override Size MeasureOverride(Size availableSize)
{
if (this.Width > 0 && this.Height > 0)
return new Size(this.Width, this.Height);
return base.MeasureOverride(availableSize);
}
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... con-in-wpf