在 Silverlight 中绑定动画的 Duration 属性

发布于 2024-11-11 13:48:10 字数 1500 浏览 4 评论 0原文

我有一个 DoubleAnimation,我想绑定它的 From、To 和 Duration 属性,以便它们能够平滑地改变。

From 和 To 的绑定效果很好,可以顺利地更改它们,但 Duration 的更改只是被忽略。

为了进行调试,我制作了一个按钮,单击该按钮即可调用包含 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 发生变化。因此,如果有其他方法可以实现这一点,那就更好了。

谢谢。

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

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.

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

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

发布评论

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

评论(2

铁轨上的流浪者 2024-11-18 13:48:10

有两个问题:您的绑定源(ViewModel)是如何编写的,以及您是否更新了数据上下文。这是我的代码并且它有效。

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

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");
            }
        }
    }
}
旧时浪漫 2024-11-18 13:48:10

我知道我来晚了,但问题是 Duration 不是 DependencyProperty,因此 WPF 不会侦听值更改事件,因此在值更改时不会更新动画 - 这与仅存储对象中的更新值。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文