關於WPF裡面動態圖片(Animate Image)和靜態圖片(Static Image)並存問題
要在 WPF 程式上顯示一般圖片(BMP、JPG、PNG、GIF..) 都不是甚麼太大問題,大概像下面一樣用 image 標籤即可。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Grid.Column="1" Grid.Row="0" Source="D:\MyImages\Taiwanmap.jpg"/>
</Grid>
但遇到動畫圖檔 GIFa 就是一件麻煩事了。
這個 image 標籤遇到 GIFa 就只能顯示第一張畫面,然後也不會有動畫。
<Image Grid.Column="1" Grid.Row="0" Source="D:\MyImages\cutecoupletogether.gif"/>
我的目的是需要的是在同一種圖像元件標籤下,能夠同時顯示動畫或是靜態圖片的方法。
也就是說如果我要做一個圖片展示區或清單(動態生成),就很難去依照圖片類型一直去更換樣版標籤,所以我希望一種標籤就能夠解決問題。
能夠支援的標籤類型當然不是只有 Image,還有很多種方法:
(底下標籤都會加上 Grid.Column 和 Grid.Row 屬性,因為我會放在上面 Grid 版面上的)
1、 MediaElement 標籤,他也可放置靜態圖片或動態圖片,但這個標籤早期只能支援URI方式提供來源,不過 .NET 4.0後 好像就改成可以放置路徑。
我試圖在 MediaElement 放置 gif 圖片
<MediaElement x:Name="element2" Grid.Column="1" Grid.Row="1" Source="D:\downloads\images\cutecoupletogether.gif" />
但它只播放一次(1 Loop)就停止了,所以我嘗試做成 RepeatBehavior="Forever" 但也只是播放一次而已。而且如果只是放靜態圖片來說:它的用法太複雜,因為要加入一堆 StoryBord 標籤來處理。
<MediaElement Name="myMediaElement" Grid.Column="0" Grid.Row="1">
<MediaElement.Triggers>
<EventTrigger RoutedEvent="MediaElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<MediaTimeline Source="D:\MyImages\cutecoupletogether.gif" Storyboard.TargetName="myMediaElement" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</MediaElement.Triggers>
</MediaElement>
MediaElement 標籤 還有一個處理方式就是在媒體播放結束事件 MediaEnded 加上處理方法
像是這樣:
<MediaElement x:Name="element" LoadedBehavior="Play" Source="D:\MyImages\rabbit.bmp" MediaEnded="MediaElement_MediaEnded"/>
這個 MediaElement_MediaEnded 方法就是處理撥放時間點,讓它往前多撥放1毫秒達到重播效果。
private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
((MediaElement)sender).Position = ((MediaElement)sender).Position.Add(TimeSpan.FromMilliseconds(1));
}
只是這樣做有個很大問題,當你 Source 放入的是靜態圖片時,可能會讓電腦大當機(感覺好像是計算時間造成溢位發生的)!!!
這也是個解決方式,畢竟 PicturxBox 在 Window Forms 時代也是一個很強大物件
首先要把兩個參考加進來:
Syatem.Windows.Forms
WindowsFormsIntergration.dll (C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF)
先在XAML加入 NS
xmlns:WinFormControls="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
然後使用 PicturxBox 控件:
<WindowsFormsHost Grid.Column="2" Grid.Row="0">
<WinFormControls:PictureBox ImageLocation="D:\MyImages\cutecoupletogether.gif" SizeMode="Zoom"/>
</WindowsFormsHost>
也是可以達成,只不過.....這種用法非常不是 WPF 要的方式,而且當程式移轉到Windows RT/Windows Phone 時會無法編譯,因為Windows Forms 是 PC 的函式庫。
3、接下來就是自訂控件,就是拿 Image 標籤下去擴充功能,讓它可以處理動畫。
這部分應用來自 Thomas Levesque 的相關技術:
第一種就是使用記憶體將動畫分頁儲存後播放方式
[參考這裡]
作者將他的作品封裝成套件 WpfAnimatedGif 放在 NuGet 上
下載 WpfAnimatedGif 到你的專案以後
在使用的 xaml 檔案上宣告 NameSpace
xmlns:gifa="http://wpfanimatedgif.codeplex.com"
然後在顯示的 image 標籤上添加屬性 gifa:ImageBehavior.AnimatedSource
<Image Grid.Column="3" Grid.Row="0" gifa:ImageBehavior.AnimatedSource = "D:\MyImages\cutecoupletogether.gif"/>
第二種就是採用 WriteableBitmap 做為核心宣染處理方式
[參考這裡]
作者將他的作品封裝成套件 XamlAnimatedGif 放在 NuGet 上
下載 XamlAnimatedGif 到你的專案以後
在使用的 xaml 檔案上宣告 NameSpace
xmlns:gifb="clr-namespace:XamlAnimatedGif;assembly=XamlAnimatedGif"
然後在顯示的 image 標籤上添加屬性 gifb:AnimationBehavior.SourceUri
<Image Grid.Column="3" Grid.Row="1" gifb:AnimationBehavior.SourceUri="D:\MyImages\cutecoupletogether.gif"/>
使用上非常的簡潔便利,而且 Image 本身就是 WPF 特性的控件,蠻符合 WPF 開發風格的。
參考:
[WPF] DISPLAY AN ANIMATED GIF IMAGE
A NEW LIBRARY TO DISPLAY ANIMATED GIFS IN XAML APPS
WPF中显示GIF图片 -CSDN
[WPF疑难]在WPF中显示动态GIF
留言