web-dev-qa-db-fra.com

Animer Gif dans WPF

J'utilise ce code pour gif Animation in seprate library Et xaml dans mon projet principal 

<controls:GifImage GifSource="/project;component/Images/my.gif" Stretch="None" />

Gif Animating (fichier séparé):

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(String.Format("pack://application:,,,{0}", 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
    }

mais j'obtiens une erreur:

Le préfixe URI n'est pas reconnu.

Je ne sais pas pourquoi je reçois une erreur. Quelqu'un peut-il m'aider, s'il vous plaît ?

11
UFO

Il existe un moyen beaucoup plus facile de montrer un fichier .gif animé dans wpf - utilisez la variable MediaElement

Exemple:

<MediaElement x:Name="myGif" MediaEnded="myGif_MediaEnded" UnloadedBehavior="Manual"     Source="file://C:\waiting.GIF" LoadedBehavior="Play" Stretch="None"/>

Si vous souhaitez que le fichier .gif se répète en boucle, mais qu'il ne spécifie qu'un nombre limité de répétitions dans le fichier .gif, vous pouvez accrocher MediaEnded et simplement relancer l'animation (veillez à définir UnloadedBehavior sur Manual):

    private void myGif_MediaEnded(object sender, RoutedEventArgs e)
    {
        myGif.Position = new TimeSpan(0, 0, 1);
        myGif.Play();
    }
24
edtheprogrammerguy

Essaye ça:

<controls:GifImage GifSource="/Images/my.gif" Stretch="None" />

BTW, j'ai trouvé en utilisant cette façon de jouer gif dans wpf pourrait déformer certaines images gif, et je me demande pourquoi ... 

0
Chobits

Je ne peux pas en accepter le mérite, mais voici une façon de le faire uniquement en XAML. J'ai ajouté une propriété "IsBusy" à mon ViewModel pour afficher/masquer le compteur pendant le traitement.

        <Image Name="Spinner" Source="Resources/spinner.gif" RenderTransformOrigin="0.5, 0.5">
            <Image.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard Storyboard.TargetName="Spinner" Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)">
                                <DoubleAnimation From="0" To="360" BeginTime="0:0:0" Duration="0:0:2" RepeatBehavior="Forever" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Image.Triggers>
            <Image.RenderTransform>
                <RotateTransform Angle="0" />
            </Image.RenderTransform>
            <Image.Style>
                <Style TargetType="Image">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsBusy}" Value="False">
                            <Setter Property="Visibility" Value="Hidden"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>

Voici le link à la solution de l'auteur.

0
LawMan