WPF 加載和顯示 GIF 圖片的完整指南
在 WPF 中加載和顯示 GIF 圖片需要一些特殊處理,因為 WPF 的 Image
控件默認不支持動畫 GIF。
解決方案一:使用 WpfAnimatedGif 庫(推薦)
這是最簡單且功能最完整的方法。
實現步驟:
-
安裝 NuGet 包:
在 NuGet 包管理器中安裝WpfAnimatedGif
:Install-Package WpfAnimatedGif
-
XAML 實現:
<Window x:Class="GifDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:gif="http://wpfanimatedgif.codeplex.com"mc:Ignorable="d"Title="GIF 動畫演示" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 加載 GIF 圖片 --><Image x:Name="gifImage" gif:ImageBehavior.AnimatedSource="Assets/loading.gif"gif:ImageBehavior.RepeatBehavior="Forever"Stretch="Uniform"HorizontalAlignment="Center"VerticalAlignment="Center"/><!-- 控制面板 --><StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"><Button Content="開始" Click="PlayGif" Margin="5" Padding="10,5"/><Button Content="暫停" Click="PauseGif" Margin="5" Padding="10,5"/><Button Content="恢復" Click="ResumeGif" Margin="5" Padding="10,5"/><Button Content="停止" Click="StopGif" Margin="5" Padding="10,5"/><ComboBox x:Name="gifSelector" Margin="10,0" Width="150"SelectionChanged="GifSelectionChanged"><ComboBoxItem Content="加載動畫" Tag="Assets/loading.gif"/><ComboBoxItem Content="慶祝動畫" Tag="Assets/celebration.gif"/><ComboBoxItem Content="進度動畫" Tag="Assets/progress.gif"/></ComboBox></StackPanel></Grid> </Window>
-
代碼后臺:
using System.Windows; using WpfAnimatedGif;namespace GifDemo {public partial class MainWindow : Window{public MainWindow(){InitializeComponent();// 設置默認選擇gifSelector.SelectedIndex = 0;}// 播放 GIFprivate void PlayGif(object sender, RoutedEventArgs e){ImageBehavior.SetAnimatedSource(gifImage, new BitmapImage(new Uri("Assets/loading.gif", UriKind.Relative)));}// 暫停 GIFprivate void PauseGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Pause();}// 恢復播放private void ResumeGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Play();}// 停止 GIFprivate void StopGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Dispose();gifImage.Source = null;}// 切換 GIFprivate void GifSelectionChanged(object sender, RoutedEventArgs e){if (gifSelector.SelectedItem is ComboBoxItem item && item.Tag is string gifPath){var source = new BitmapImage(new Uri(gifPath, UriKind.Relative));ImageBehavior.SetAnimatedSource(gifImage, source);}}} }
解決方案二:使用自定義 GIF 解碼器
如果你不想使用第三方庫,可以使用自定義實現:
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;namespace GifDemo
{public partial class MainWindow : Window{private Bitmap _gifBitmap;private BitmapSource[] _gifFrames;private int _currentFrame;private bool _isPlaying;private readonly DispatcherTimer _animationTimer = new DispatcherTimer();public MainWindow(){InitializeComponent();_animationTimer.Tick += NextFrame;}private void LoadGif(string path){// 清理現有資源StopGif();// 加載新 GIF_gifBitmap = new Bitmap(path);// 獲取幀數int frameCount = _gifBitmap.GetFrameCount(FrameDimension.Time);_gifFrames = new BitmapSource[frameCount];// 提取所有幀for (int i = 0; i < frameCount; i++){_gifBitmap.SelectActiveFrame(FrameDimension.Time, i);_gifFrames[i] = ToBitmapSource(_gifBitmap);}// 獲取幀延遲var frameDelay = GetFrameDelay(_gifBitmap);_animationTimer.Interval = TimeSpan.FromMilliseconds(frameDelay);// 顯示第一幀_currentFrame = 0;gifImage.Source = _gifFrames[0];// 開始播放PlayGif();}private int GetFrameDelay(Bitmap gif){const int PropertyTagFrameDelay = 0x5100;// 獲取幀延遲屬性var delayProperty = gif.GetPropertyItem(PropertyTagFrameDelay);// 默認延遲 (100ms)if (delayProperty == null) return 100;// 返回第一幀的延遲(以毫秒為單位)return BitConverter.ToInt32(delayProperty.Value, 0) * 10;}private BitmapSource ToBitmapSource(Bitmap bitmap){using (var memory = new MemoryStream()){bitmap.Save(memory, ImageFormat.Png);memory.Position = 0;var bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.StreamSource = memory;bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.EndInit();bitmapImage.Freeze();return bitmapImage;}}private void NextFrame(object sender, EventArgs e){if (!_isPlaying || _gifFrames == null) return;_currentFrame = (_currentFrame + 1) % _gifFrames.Length;gifImage.Source = _gifFrames[_currentFrame];}private void PlayGif(object sender = null, RoutedEventArgs e = null){_isPlaying = true;_animationTimer.Start();}private void PauseGif(object sender, RoutedEventArgs e){_isPlaying = false;_animationTimer.Stop();}private void StopGif(object sender = null, RoutedEventArgs e = null){_isPlaying = false;_animationTimer.Stop();_currentFrame = 0;gifImage.Source = _gifFrames?[0];}protected override void OnClosed(EventArgs e){base.OnClosed(e);_animationTimer.Stop();_gifBitmap?.Dispose();}}
}
解決方案三:使用 MediaElement(適用于簡單 GIF)
對于不需要透明背景的 GIF,可以使用 MediaElement:
<Window x:Class="GifDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="GIF 動畫演示" Height="450" Width="800"><Grid><!-- 使用 MediaElement 播放 GIF --><MediaElement x:Name="mediaElement" Source="Assets/loading.gif"LoadedBehavior="Play"UnloadedBehavior="Stop"Stretch="Uniform"HorizontalAlignment="Center"VerticalAlignment="Center"/><!-- 控制面板 --><StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="10"><Button Content="播放" Click="PlayGif" Margin="5" Padding="10,5"/><Button Content="暫停" Click="PauseGif" Margin="5" Padding="10,5"/><Button Content="停止" Click="StopGif" Margin="5" Padding="10,5"/></StackPanel></Grid>
</Window>
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private void PlayGif(object sender, RoutedEventArgs e){mediaElement.Play();}private void PauseGif(object sender, RoutedEventArgs e){mediaElement.Pause();}private void StopGif(object sender, RoutedEventArgs e){mediaElement.Stop();}
}
常見問題解決方案
1. GIF 不播放
- 檢查文件路徑是否正確
- 確保 GIF 文件已設置為 “Resource” 或 “Content” 生成操作
- 驗證 GIF 文件是否損壞(用其他軟件打開測試)
2. 透明背景顯示為黑色
- 使用支持透明背景的解決方案(如 WpfAnimatedGif)
- 確保 GIF 本身支持透明
- 在 Image 控件上設置
Background="Transparent"
3. 性能問題
- 避免加載過多 GIF
- 暫停不可見的 GIF
- 降低 GIF 分辨率
- 使用
BitmapCache
提高渲染性能:<Image.CacheMode><BitmapCache EnableClearType="True" RenderAtScale="1" /> </Image.CacheMode>
4. 控制 GIF 播放次數
<Image gif:ImageBehavior.AnimatedSource="animation.gif"gif:ImageBehavior.RepeatBehavior="3x"/> <!-- 播放3次 -->
總結
在 WPF 中加載和顯示 GIF 圖片有以下幾種方法:
-
推薦方案:使用
WpfAnimatedGif
NuGet 包- 優點:功能完整、支持透明背景、易于使用
- 缺點:需要添加外部依賴
-
自定義解碼器:
- 優點:無外部依賴
- 缺點:實現復雜、功能有限
-
使用 MediaElement:
- 優點:內置支持
- 缺點:不支持透明背景、功能有限
對于大多數應用場景,推薦使用 WpfAnimatedGif
庫,它提供了最完整的 GIF 支持,包括:
- 播放控制(播放、暫停、停止)
- 速度調整
- 播放次數控制
- 透明背景支持
- 事件通知(如幀改變、播放完成等)
通過本文提供的代碼示例,您可以輕松地在 WPF 應用中實現 GIF 加載和播放功能,并根據需要添加自定義控制功能。