我应该使用什么控件类型-图像,MediaElement等?
当前回答
我修改了迈克·艾希瓦的代码,让它运行得更好。你可以使用它与1帧jpg png bmp或多帧gif。如果你想绑定uri到控件,绑定UriSource属性,或者你想绑定任何内存流,你绑定Source属性,这是一个BitmapImage。
/// <summary>
/// Элемент управления "Изображения", поддерживающий анимированные GIF.
/// </summary>
public class AnimatedImage : Image
{
static AnimatedImage()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage)));
}
#region Public properties
/// <summary>
/// Получает/устанавливает номер текущего кадра.
/// </summary>
public int FrameIndex
{
get { return (int)GetValue(FrameIndexProperty); }
set { SetValue(FrameIndexProperty, value); }
}
/// <summary>
/// Get the BitmapFrame List.
/// </summary>
public List<BitmapFrame> Frames { get; private set; }
/// <summary>
/// Get or set the repeatBehavior of the animation when source is gif formart.This is a dependency object.
/// </summary>
public RepeatBehavior AnimationRepeatBehavior
{
get { return (RepeatBehavior)GetValue(AnimationRepeatBehaviorProperty); }
set { SetValue(AnimationRepeatBehaviorProperty, value); }
}
public new BitmapImage Source
{
get { return (BitmapImage)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public Uri UriSource
{
get { return (Uri)GetValue(UriSourceProperty); }
set { SetValue(UriSourceProperty, value); }
}
#endregion
#region Protected interface
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Source property.
/// </summary>
protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e)
{
ClearAnimation();
BitmapImage source;
if (e.NewValue is Uri)
{
source = new BitmapImage();
source.BeginInit();
source.UriSource = e.NewValue as Uri;
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
}
else if (e.NewValue is BitmapImage)
{
source = e.NewValue as BitmapImage;
}
else
{
return;
}
BitmapDecoder decoder;
if (source.StreamSource != null)
{
decoder = BitmapDecoder.Create(source.StreamSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
}
else if (source.UriSource != null)
{
decoder = BitmapDecoder.Create(source.UriSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
}
else
{
return;
}
if (decoder.Frames.Count == 1)
{
base.Source = decoder.Frames[0];
return;
}
this.Frames = decoder.Frames.ToList();
PrepareAnimation();
}
#endregion
#region Private properties
private Int32Animation Animation { get; set; }
private bool IsAnimationWorking { get; set; }
#endregion
#region Private methods
private void ClearAnimation()
{
if (Animation != null)
{
BeginAnimation(FrameIndexProperty, null);
}
IsAnimationWorking = false;
Animation = null;
this.Frames = null;
}
private void PrepareAnimation()
{
Animation =
new Int32Animation(
0,
this.Frames.Count - 1,
new Duration(
new TimeSpan(
0,
0,
0,
this.Frames.Count / 10,
(int)((this.Frames.Count / 10.0 - this.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
base.Source = this.Frames[0];
BeginAnimation(FrameIndexProperty, Animation);
IsAnimationWorking = true;
}
private static void ChangingFrameIndex
(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
AnimatedImage animatedImage = dp as AnimatedImage;
if (animatedImage == null || !animatedImage.IsAnimationWorking)
{
return;
}
int frameIndex = (int)e.NewValue;
((Image)animatedImage).Source = animatedImage.Frames[frameIndex];
animatedImage.InvalidateVisual();
}
/// <summary>
/// Handles changes to the Source property.
/// </summary>
private static void OnSourceChanged
(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
((AnimatedImage)dp).OnSourceChanged(e);
}
#endregion
#region Dependency Properties
/// <summary>
/// FrameIndex Dependency Property
/// </summary>
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register(
"FrameIndex",
typeof(int),
typeof(AnimatedImage),
new UIPropertyMetadata(0, ChangingFrameIndex));
/// <summary>
/// Source Dependency Property
/// </summary>
public new static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(
"Source",
typeof(BitmapImage),
typeof(AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
/// <summary>
/// AnimationRepeatBehavior Dependency Property
/// </summary>
public static readonly DependencyProperty AnimationRepeatBehaviorProperty =
DependencyProperty.Register(
"AnimationRepeatBehavior",
typeof(RepeatBehavior),
typeof(AnimatedImage),
new PropertyMetadata(null));
public static readonly DependencyProperty UriSourceProperty =
DependencyProperty.Register(
"UriSource",
typeof(Uri),
typeof(AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
#endregion
}
这是一个自定义控件。您需要在WPF应用程序项目中创建它,并在样式中删除模板覆盖。
其他回答
检查我的代码,我希望这对你有帮助:)
public async Task GIF_Animation_Pro(string FileName,int speed,bool _Repeat)
{
int ab=0;
var gif = GifBitmapDecoder.Create(new Uri(FileName), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var getFrames = gif.Frames;
BitmapFrame[] frames = getFrames.ToArray();
await Task.Run(() =>
{
while (ab < getFrames.Count())
{
Thread.Sleep(speed);
try
{
Dispatcher.Invoke(() =>
{
gifImage.Source = frames[ab];
});
if (ab == getFrames.Count - 1&&_Repeat)
{
ab = 0;
}
ab++;
}
catch
{
}
}
});
}
or
public async Task GIF_Animation_Pro(Stream stream, int speed,bool _Repeat)
{
int ab = 0;
var gif = GifBitmapDecoder.Create(stream , BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var getFrames = gif.Frames;
BitmapFrame[] frames = getFrames.ToArray();
await Task.Run(() =>
{
while (ab < getFrames.Count())
{
Thread.Sleep(speed);
try
{
Dispatcher.Invoke(() =>
{
gifImage.Source = frames[ab];
});
if (ab == getFrames.Count - 1&&_Repeat)
{
ab = 0;
}
ab++;
}
catch{}
}
});
}
它非常简单,如果你使用<MediaElement>:
<MediaElement Height="113" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="mediaElement1" VerticalAlignment="Top" Width="198" Source="C:\Users\abc.gif"
LoadedBehavior="Play" Stretch="Fill" SpeedRatio="1" IsMuted="False" />
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;
}
这是我的动画图像控制版本。您可以使用标准属性Source来指定图像源。我进一步改进了它。我是俄罗斯人,项目是俄罗斯的,所以评论也是俄语。但是无论如何,你应该能够理解没有注释的一切。:)
/// <summary>
/// Control the "Images", which supports animated GIF.
/// </summary>
public class AnimatedImage : Image
{
#region Public properties
/// <summary>
/// Gets / sets the number of the current frame.
/// </summary>
public int FrameIndex
{
get { return (int) GetValue(FrameIndexProperty); }
set { SetValue(FrameIndexProperty, value); }
}
/// <summary>
/// Gets / sets the image that will be drawn.
/// </summary>
public new ImageSource Source
{
get { return (ImageSource) GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
#endregion
#region Protected interface
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Source property.
/// </summary>
protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs aEventArgs)
{
ClearAnimation();
BitmapImage lBitmapImage = aEventArgs.NewValue as BitmapImage;
if (lBitmapImage == null)
{
ImageSource lImageSource = aEventArgs.NewValue as ImageSource;
base.Source = lImageSource;
return;
}
if (!IsAnimatedGifImage(lBitmapImage))
{
base.Source = lBitmapImage;
return;
}
PrepareAnimation(lBitmapImage);
}
#endregion
#region Private properties
private Int32Animation Animation { get; set; }
private GifBitmapDecoder Decoder { get; set; }
private bool IsAnimationWorking { get; set; }
#endregion
#region Private methods
private void ClearAnimation()
{
if (Animation != null)
{
BeginAnimation(FrameIndexProperty, null);
}
IsAnimationWorking = false;
Animation = null;
Decoder = null;
}
private void PrepareAnimation(BitmapImage aBitmapImage)
{
Debug.Assert(aBitmapImage != null);
if (aBitmapImage.UriSource != null)
{
Decoder = new GifBitmapDecoder(
aBitmapImage.UriSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
}
else
{
aBitmapImage.StreamSource.Position = 0;
Decoder = new GifBitmapDecoder(
aBitmapImage.StreamSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
}
Animation =
new Int32Animation(
0,
Decoder.Frames.Count - 1,
new Duration(
new TimeSpan(
0,
0,
0,
Decoder.Frames.Count / 10,
(int) ((Decoder.Frames.Count / 10.0 - Decoder.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
base.Source = Decoder.Frames[0];
BeginAnimation(FrameIndexProperty, Animation);
IsAnimationWorking = true;
}
private bool IsAnimatedGifImage(BitmapImage aBitmapImage)
{
Debug.Assert(aBitmapImage != null);
bool lResult = false;
if (aBitmapImage.UriSource != null)
{
BitmapDecoder lBitmapDecoder = BitmapDecoder.Create(
aBitmapImage.UriSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
lResult = lBitmapDecoder is GifBitmapDecoder;
}
else if (aBitmapImage.StreamSource != null)
{
try
{
long lStreamPosition = aBitmapImage.StreamSource.Position;
aBitmapImage.StreamSource.Position = 0;
GifBitmapDecoder lBitmapDecoder =
new GifBitmapDecoder(
aBitmapImage.StreamSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
lResult = lBitmapDecoder.Frames.Count > 1;
aBitmapImage.StreamSource.Position = lStreamPosition;
}
catch
{
lResult = false;
}
}
return lResult;
}
private static void ChangingFrameIndex
(DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
{
AnimatedImage lAnimatedImage = aObject as AnimatedImage;
if (lAnimatedImage == null || !lAnimatedImage.IsAnimationWorking)
{
return;
}
int lFrameIndex = (int) aEventArgs.NewValue;
((Image) lAnimatedImage).Source = lAnimatedImage.Decoder.Frames[lFrameIndex];
lAnimatedImage.InvalidateVisual();
}
/// <summary>
/// Handles changes to the Source property.
/// </summary>
private static void OnSourceChanged
(DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
{
((AnimatedImage) aObject).OnSourceChanged(aEventArgs);
}
#endregion
#region Dependency Properties
/// <summary>
/// FrameIndex Dependency Property
/// </summary>
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register(
"FrameIndex",
typeof (int),
typeof (AnimatedImage),
new UIPropertyMetadata(0, ChangingFrameIndex));
/// <summary>
/// Source Dependency Property
/// </summary>
public new static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(
"Source",
typeof (ImageSource),
typeof (AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
#endregion
}
添加到主响应,建议使用WpfAnimatedGif,你必须在最后添加以下行,如果你是交换图像与Gif,以确保动画实际执行:
ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);
所以你的代码看起来像这样:
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fileName);
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);
推荐文章
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- AppSettings从.config文件中获取值
- 如何检查IEnumerable是否为空或空?
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 如何在iis7应用程序池中设置。net Framework 4.5版本
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何指定最小值,但没有使用范围数据注释属性的最大小数?
- 如何在PowerShell中获得本地主机名?
- 为什么在Java和。net中不能修改字符串?
- 禁用Visual Studio 2015额外调试选项
- 'throw'和'throw new Exception()'的区别
- c# int到字节[]
- 如何跟踪log4net问题