2010-07-28 2 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 
} 

}

내 애니메이션 용 GIF를 표시하려는 XAML은 다음과 같습니다.

<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" />

'속성 설정'WpfBrowserApplication1.AnimatedImage.Source '가 예외를 throw했습니다.' 줄 번호 '11'과 줄 위치 '21'.

나는 이것을 잠깐 동안 작동 시키려고 노력해 왔습니다. 프로젝트가 실행될 때 이미지에 애니메이션을 적용하려면 어떻게해야합니까?

답변

3

편집 :

XAML :

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

참고 :

당신은 전체 프로젝트 from my blog을 다운로드 할 수 있습니다 이것은 잘 작동

을 (스티브을 클릭) 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 접두어가 인식되지 않습니다." –

+0

내 잘못, 이미지 경로 앞에 "/"접두사가 필요합니다 : GifSource = "/ SomeImage.gif". 나는 대답에서 그것을 고칠 것이다. – Carlo

+0

-1을 1로 변경하면 지금 작동합니다. –

관련 문제