在Silverlight中绑定动画的Duration属性

时间:2011-06-01 20:26:58

标签: wpf silverlight animation binding duration

我有一个DoubleAnimation,我想绑定它的From,To和Duration属性,以便它们可以顺利改变。

From和To的绑定效果很好,可以顺利更改它们,但是持续时间的更改只是被忽略了。

为了进行调试,我创建了一个按钮,在单击时调用包含StoryBoard的Stop和Begin方法,动画从头开始,持续时间正确。此外,我检查并看到动画的Duration属性实际上每次都在更新,因此动画会忽略更改。 (与真正反应顺畅的From和To不同。)

在WPF中尝试了同样的结果并获得了相同的结果,这是一个片段:

        <Canvas>
        <Canvas.Triggers>
            <EventTrigger RoutedEvent="Canvas.Loaded">
                <BeginStoryboard>
                    <Storyboard x:Name="Story">
                        <DoubleAnimation x:Name="Anime"
                                         Duration="{Binding Duration}"
                                         RepeatBehavior="Forever"
                                         Storyboard.TargetName="Text1"
                                         Storyboard.TargetProperty="(Canvas.Left)"                                             
                                         From="0"
                                         To="400"                                             
                                         />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Canvas.Triggers>
        <TextBlock Text="Hello" Name="Text1"/>
    </Canvas>

我真的很感激解释为什么这不起作用以及任何可以使绑定顺利过渡的解决方法。

此外,我的实际最终目标是让TextBlock以恒定速度移动,尽管From和To有所变化。因此,如果有另一种方法可以实现这一目标,那就更好了。

感谢。

2 个答案:

答案 0 :(得分:1)

有两个问题:如何编写绑定源(ViewModel),并更新了datacontext。这是我的代码,它可以工作。

MainPage.xaml:

<Canvas>
    <Canvas.Triggers>
        <EventTrigger RoutedEvent="Canvas.Loaded">
            <BeginStoryboard>
                <Storyboard x:Name="Story">
                    <DoubleAnimation x:Name="Anime"
                                     Duration="{Binding}"
                                     RepeatBehavior="Forever"
                                     Storyboard.TargetName="Text1"
                                     Storyboard.TargetProperty="(Canvas.Left)"                                             
                                     From="0"
                                     To="400"                                             
                                     />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Canvas.Triggers>
    <TextBlock Text="Hello" Name="Text1"/>
    <Button Content="Change" Margin="0, 100, 0, 0" Click="Button_Click" />
</Canvas>

MainPage.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace SilverlightApplication
{
    public partial class MainPage : UserControl
    {
        AnimVM vm = new AnimVM();
        double dur = 5;

        public MainPage()
        {
            InitializeComponent();

            vm.Duration = new Duration(TimeSpan.FromSeconds(dur));

            this.DataContext = vm.Duration;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            dur += 5;
            vm.Duration = new Duration(TimeSpan.FromSeconds(dur));
            this.DataContext = vm.Duration; // don't forget this line
        }
    }

    public class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        protected ViewModelBase()
        {
        }

        protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            //this.VerifyPropertyName(propertyName);

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        public void Dispose()
        {
            this.OnDispose();
        }

        protected virtual void OnDispose()
        {
        }
    }

    public class AnimVM : ViewModelBase
    {
        private Duration _duration = new Duration(TimeSpan.FromSeconds(5));
        public Duration Duration
        {
            get { return _duration; }
            set
            {
                if (object.ReferenceEquals(this._duration, value)) return;

                this._duration = value;
                base.OnPropertyChanged("Duration");
            }
        }
    }
}

答案 1 :(得分:0)

我知道我迟到了,但问题是持续时间不是DependencyProperty,所​​以WPF没有收听值更改事件,因此当值发生变化时不会更新动画 - 这与只是将更新后的值存储在对象中。