我应该使用什么控件类型-图像,MediaElement等?
当前回答
我建议使用WebBrowser控件。
如果gif在网络上,你可以在XAML中设置源代码:
<WebBrowser Source="https://media.giphy.com/media/Ent2j55lyQipa/giphy.gif" />
如果它是一个本地文件,您可以从后台代码创建源代码。
XAML:
<WebBrowser x:Name="WebBrowser" />
后台代码:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string curDir = Directory.GetCurrentDirectory();
this.WebBrowser.Source = new Uri(String.Format("file:///{0}/10-monkey.gif", curDir));
}
其他回答
基本上与上面的PictureBox解决方案相同,但这次使用了在项目中使用嵌入式资源的幕后代码:
在XAML:
<WindowsFormsHost x:Name="_loadingHost">
<Forms:PictureBox x:Name="_loadingPictureBox"/>
</WindowsFormsHost>
在后台代码:
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;
}
}
我有这个问题,直到我发现在WPF4,你可以模拟自己的关键帧图像动画。首先,将你的动画分割成一系列图像,并将它们命名为“Image1.gif”,“Image2,gif”,等等。将这些映像导入您的解决方案资源中。我假设您将它们放在图像的默认资源位置。
您将使用Image控件。使用下面的XAML代码。我已经去掉了不重要的部分。
<Image Name="Image1">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded"
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="Source" RepeatBehavior="Forever">
<DiscreteObjectKeyFrames KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image1.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.25">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image2.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image3.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.75">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image4.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image5.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Image.Triggers>
</Image>
GifImage.Initialize()方法的小改进,该方法从GIF元数据中读取适当的帧定时。
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;
}
在WPF中等待动画的替代方法是:
<ProgressBar Height="20" Width="100" IsIndeterminate="True"/>
它将显示一个动画进度条。
上面的方法我都试过了,但每个方法都有自己的不足,感谢大家,我想出了自己的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
/// <summary>
/// Defines whether the animation starts on it's own
/// </summary>
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));
}
/// <summary>
/// Starts the animation
/// </summary>
public void StartAnimation()
{
if (!_isInitialized)
this.Initialize();
// Console.WriteLine("Start: " + GifSource);
System.Drawing.ImageAnimator.Animate(_bitmap, OnFrameChanged);
}
/// <summary>
/// Stops the animation
/// </summary>
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);
}
}
}
用法:
<localComponents:GifImage x:Name="gifImage" IsAutoStart="True" GifSource="{Binding Path=value}" />
因为它不会导致内存泄漏,它动画gif图像自己的时间线,你可以尝试一下。
推荐文章
- c# .NET中的App.config是什么?如何使用它?
- String类中的什么方法只返回前N个字符?
- 我如何提高ASP。NET MVC应用程序性能?
- 无法解析类型为“Microsoft.AspNetCore.Http.IHttpContextAccessor”的服务
- 如何在没有任何错误或警告的情况下找到构建失败的原因
- Visual Studio弹出提示:“操作无法完成”
- 否ConcurrentList<T>在。net 4.0?
- 在c#中解析字符串为日期时间
- 由Jon Skeet撰写的《Singleton》澄清
- 自定义数字格式字符串始终显示符号
- Post参数始终为空
- string.ToLower()和string.ToLowerInvariant()
- 检查instance是否属于某个类型
- 将列表转换为逗号分隔的字符串
- Microsoft.Jet.OLEDB.4.0'提供程序未在本地机器上注册