开发者

Binding the Duration property of an animation in Silverlight

I have a DoubleAnimation that I want to bind its From, To and Duration Properties so they would change smoothly.

The binding of From and To works great, changes them smoothly, but the changes of the Duration are simply being ignor开发者_JAVA百科ed.

For debugging, I made a button that on click calls the Stop and Begin methods of the containing StoryBoard, and the animation started from the beginning with the correct duration. Also I checked and saw that the Duration property of the animation is actually being updated everytime, so the change is just being ignored by the animation. (Unlike the From and To that really react smoothly.)

Tried the same in WPF and got the same results, here's a snippet:

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

I would really appreciate an explanation why isn't this working and any workarounds that would make the binding work with a smooth transition.

Also, the actual final goal of mine is to have the TextBlock moving in constant speed despite changes in From and To. So if there is another way of achieving this, it would be even better.

Thanks.


There are two concern: how is your binding source (ViewModel) written, and did you update your datacontext. Here is my code and it works.

the 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>

the 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");
            }
        }
    }
}


I know I am way late to the party, but the problem is that Duration is not a DependencyProperty, so WPF is not listening to the value change event, and therefore not updating the animation when the value changes - that is different than just storing the updated value in the object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜