我应该使用什么控件类型-图像,MediaElement等?
当前回答
上面的方法我都试过了,但每个方法都有自己的不足,感谢大家,我想出了自己的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图像自己的时间线,你可以尝试一下。
其他回答
检查我的代码,我希望这对你有帮助:)
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{}
}
});
}
我使用这个库:https://github.com/XamlAnimatedGif/WpfAnimatedGif
首先,将库安装到项目中(使用包管理器控制台):
PM > Install-Package WpfAnimatedGif
然后,使用这个片段到XAML文件:
<Window x:Class="WpfAnimatedGif.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />
...
希望能有所帮助。
来源:https://github.com/XamlAnimatedGif/WpfAnimatedGif
我有这个问题,直到我发现在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>
这个小程序怎么样: 背后的代码:
public MainWindow()
{
InitializeComponent();
Files = Directory.GetFiles(@"I:\images");
this.DataContext= this;
}
public string[] Files
{get;set;}
XAML:
<Window x:Class="PicViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="lst" ItemsSource="{Binding Path=Files}"/>
<MediaElement Grid.Column="1" LoadedBehavior="Play" Source="{Binding ElementName=lst, Path=SelectedItem}" Stretch="None"/>
</Grid>
</Window>
在WPF中等待动画的替代方法是:
<ProgressBar Height="20" Width="100" IsIndeterminate="True"/>
它将显示一个动画进度条。
推荐文章
- 如何为构造函数定制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问题