如何让此 WPF .gif 在更新时播放?

发布于 2024-11-03 05:59:45 字数 5252 浏览 1 评论 0原文

问题

  • 为什么我的 .gif 在使用 GifSourcePropertyChanged 更新时加载但无法播放?

关于.gif加载:
目前,我使用 U.IsValidURL() 来防止 new Uri 抛出 Exception。这是因为我需要 GifImage 来加载应用程序,然后从 ViewModel 进行更新。一切都很顺利,直到调用 GifSourcePropertyChanged ,然后更新 local:GifImage ,但是 .gif 无法播放(我相信它加载为MediaElement 并行加载,local:GifImage.gif 应该加载的位置变黑)。如果我从一开始就对示例 Uri 进行硬编码,则 local:GifImage 会正常加载和播放。

示例 XAML:

<local:GifImage 
        GifSource="{    
            Binding Path=myGifImage, 
            UpdateSourceTrigger=PropertyChanged, 
            Mode=OneWay}"
        AutoStart="True"/>

示例 ViewModel:

public class ViewModel: INotifyPropertyChanged
{                   
    private string _myGifImage; 

    public string myGifImage
    {
        get { return this._myGifImage; }
        set
        {
            this._myGifImage = value;
            this.OnPropertyChanged("myGifImage");
        }
    }
}

示例 GifImage 类:

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()
    {

        if (U.IsValidURL(this.GifSource, UriKind.Absolute))
        {
            _gifDecoder = new GifBitmapDecoder(
                new Uri(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
}  

我从 SO 上的某个地方获得了 GifImage (我不能记住哪个问题,WPF.gifs 上有几个)。 GifImage 是唯一没有大量错误的类(至少对我来说)。

Question:

  • Why does my .gif load, but not play when updating using GifSourcePropertyChanged?

About .gif loading:
Currently I have use U.IsValidURL() to keep new Uri from throwing an Exception. This is because I need GifImage to load with the application and then update later from ViewModel. Everything goes fine until GifSourcePropertyChanged is called, then local:GifImage is updated, but the .gif doesn't play (I believe it loads as MediaElement loads in parallel and local:GifImage turns black where the .gif is suppose to load). If I hard code a sample Uri from the beginning, local:GifImage loads and plays just fine.

Example XAML:

<local:GifImage 
        GifSource="{    
            Binding Path=myGifImage, 
            UpdateSourceTrigger=PropertyChanged, 
            Mode=OneWay}"
        AutoStart="True"/>

Example ViewModel:

public class ViewModel: INotifyPropertyChanged
{                   
    private string _myGifImage; 

    public string myGifImage
    {
        get { return this._myGifImage; }
        set
        {
            this._myGifImage = value;
            this.OnPropertyChanged("myGifImage");
        }
    }
}

Example GifImage Class:

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()
    {

        if (U.IsValidURL(this.GifSource, UriKind.Absolute))
        {
            _gifDecoder = new GifBitmapDecoder(
                new Uri(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
}  

I got GifImage from somewhere on SO (I can't remember which question, there are several on WPF and .gifs). GifImage was the only class that didn't have a ton of errors (at least for me).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小伙你站住 2024-11-10 05:59:45

不确定您的代码有什么问题,但您可以尝试使用 此附加属性改为:

<Image my:ImageBehavior.AnimatedSource="{Binding Path=myGifImage}"/>

Not sure what the problem is with your code, but you could try to use this attached property instead:

<Image my:ImageBehavior.AnimatedSource="{Binding Path=myGifImage}"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文