2010-07-28 25 views
1

我一直在試圖從他對GIF動畫的回答讓邁克Eshva的代碼工作,從這裏開始:動畫GIF在VS2010的設計視圖中工作,但有運行時錯誤?

How do I get an animated gif to work in WPF?

這裏重述(包括翻譯的註釋):

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.Windows.Media.Animation; 
using System.Windows.Media; 
using System.Diagnostics; 

namespace WpfBrowserApplication1 { 
    /// <summary> 
    /// Control of the "Images", which supports animated GIF. 
    /// </summary> 
    public class AnimatedImage : Image { 
     public AnimatedImage() { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage))); 
     } 
    #region Public properties 

    /// <summary> 
    /// Gets/sets the number of current frame. 
    /// </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 
} 

}

這裏是我的網頁的XAML只是試圖展示一個動畫GIF:

<Page x:Class="WpfBrowserApplication1.Page1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:my="clr-namespace:WpfBrowserApplication1" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300" 
     Title="Page1"> 
    <Grid> 
     <my:AnimatedImage x:Name="Wait" Source="arrows.gif" Width="16" Height="16" /> 
    </Grid> 
</Page> 

在Page1的設計視圖中,我很高興地看到動畫gif做它應該做的事情,沒有構建錯誤,沒有設計錯誤,它只是按照它應該的方式工作。只要我啓動頁面以確保它在瀏覽器中正常工作,我會在該行看到以下錯誤:<my:AnimatedImage x:Name="Wait" Source="arrows.gif" Width="16" Height="16" />

'Set property'WpfBrowserApplication1.AnimatedImage.Source'throw a exception。'行號「11」和行位置「21」。

我一直試圖讓它工作一段時間。當項目運行時,我能做些什麼來使圖像動畫化?

回答

3

編輯:

您可以下載整個項目from my blog(點擊史蒂夫)

這一個正常工作:

XAML:

<controls:GifImage x:Name="gifImage" Stretch="None" GifSource="/SomeImage.gif" AutoStart="True" /> 

注:

如果AutoStart設置爲false,則需要調用Sh ow()或StartAnimation()手動從您的代碼。

C#:

public class GifImage : Image 
{ 
    #region Memmbers 

    private GifBitmapDecoder _gifDecoder; 
    private Int32Animation _animation; 
    private bool _isInitialized; 

    #endregion Memmbers 

    #region Properties 

    private int FrameIndex 
    { 
    get { return (int)GetValue(FrameIndexProperty); } 
    set { SetValue(FrameIndexProperty, value); } 
    } 

    private static readonly DependencyProperty FrameIndexProperty = 
    DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex))); 

    private static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev) 
    { 
    GifImage image = obj as GifImage; 
    image.Source = image._gifDecoder.Frames[(int)ev.NewValue]; 
    } 

    /// <summary> 
    /// Defines whether the animation starts on it's own 
    /// </summary> 
    public bool AutoStart 
    { 
    get { return (bool)GetValue(AutoStartProperty); } 
    set { SetValue(AutoStartProperty, value); } 
    } 

    public static readonly DependencyProperty AutoStartProperty = 
    DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged)); 

    private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
    if ((bool)e.NewValue) 
    (sender as GifImage).StartAnimation(); 
    } 

    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(string.Empty, GifSourcePropertyChanged)); 

    private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
    // CARLO 20100622: Reinitialize animation everytime image is changed 
    (sender as GifImage).Initialize(); 
    } 

    #endregion Properties 

    #region Private Instance Methods 

    private void Initialize() 
    { 
    _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); 
    _animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count/10, (int)((_gifDecoder.Frames.Count/10.0 - _gifDecoder.Frames.Count/10) * 1000)))); 
    _animation.RepeatBehavior = RepeatBehavior.Forever; 
    this.Source = _gifDecoder.Frames[0]; 

    _isInitialized = true; 
    } 

    #endregion Private Instance Methods 

    #region Public Instance Methods 

    /// <summary> 
    /// Shows and starts the gif animation 
    /// </summary> 
    public void Show() 
    { 
    this.Visibility = Visibility.Visible; 
    this.StartAnimation(); 
    } 

    /// <summary> 
    /// Hides and stops the gif animation 
    /// </summary> 
    public void Hide() 
    { 
    this.Visibility = Visibility.Collapsed; 
    this.StopAnimation(); 
    } 

    /// <summary> 
    /// Starts the animation 
    /// </summary> 
    public void StartAnimation() 
    { 
    if (!_isInitialized) 
    this.Initialize(); 

    BeginAnimation(FrameIndexProperty, _animation); 
    } 

    /// <summary> 
    /// Stops the animation 
    /// </summary> 
    public void StopAnimation() 
    { 
    BeginAnimation(FrameIndexProperty, null); 
    } 

    #endregion Public Instance Methods 
} 
+0

嘗試這個。收到NotSupportedException:「URI前綴無法識別。」 – 2010-07-29 15:58:01

+0

我不好,你需要在圖像路徑前加一個「/」來代替:GifSource =「/ SomeImage.gif」。我會在答案中解決它。 – Carlo 2010-07-29 18:10:37

+0

知道這個切換-1到1,現在它工作。 – 2010-07-29 21:13:48

相關問題