代码之家  ›  专栏  ›  技术社区  ›  Corey Ogburn

动画GIF在VS2010的设计视图中工作,但有运行时错误吗?

  •  1
  • Corey Ogburn  · 技术社区  · 15 年前

    我一直试图从他关于动画礼物的答案中得到迈克·埃什瓦的代码,从这里开始工作:

    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“引发了异常。“行号”11“和行位置”21“。”

    我试着让这个工作有一段时间了。当项目运行时,我可以做些什么使图像成为动画?

    1 回复  |  直到 15 年前
        1
  •  3
  •   Carlo    15 年前

    编辑:

    你可以下载整个项目 from my blog (点击史蒂夫)

    这个很好用:

    XAML:

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

    注:

    如果autostart设置为false,则需要从代码中手动调用show()或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
     }