WPF Storyboard运行良好,除了第一次运行。为什么?

时间:2010-06-14 08:47:06

标签: wpf

我在做Surface应用程序。 在那里,我有一个类似于公告牌的东西,其上贴有新闻的小卡片。 点击它们会飞出棋盘并扩大规模。 我的故事板运行良好,除了第一次运行。它不是一个平滑的动画,但它立即缩放到它的最终大小,它与orientation-property相同。只是中心属性似乎行为正确。

这是我的一个故事板的例子:

            Storyboard stb = new Storyboard();
            PointAnimation moveCenter = new PointAnimation();
            DoubleAnimationUsingKeyFrames changeWidth = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames changeHeight = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames changeOrientation = new DoubleAnimationUsingKeyFrames();

            moveCenter.From = News1.ActualCenter;
            moveCenter.To = new Point(250, 400);
            moveCenter.Duration = new Duration(TimeSpan.FromSeconds(1.0));
            moveCenter.FillBehavior = FillBehavior.Stop;
            stb.Children.Add(moveCenter);
            Storyboard.SetTarget(moveCenter, News1);
            Storyboard.SetTargetProperty(moveCenter, new PropertyPath(ScatterViewItem.CenterProperty));

            changeWidth.Duration = TimeSpan.FromSeconds(1);
            changeWidth.KeyFrames.Add(new EasingDoubleKeyFrame(266, KeyTime.FromTimeSpan(new System.TimeSpan(0, 0, 1))));
            changeWidth.FillBehavior = FillBehavior.Stop;
            stb.Children.Add(changeWidth);
            Storyboard.SetTarget(changeWidth, News1);
            Storyboard.SetTargetProperty(changeWidth, new PropertyPath(FrameworkElement.WidthProperty));

            changeHeight.Duration = TimeSpan.FromSeconds(1);
            changeHeight.KeyFrames.Add(new EasingDoubleKeyFrame(400, KeyTime.FromTimeSpan(new System.TimeSpan(0, 0, 1))));
            changeHeight.FillBehavior = FillBehavior.Stop;
            stb.Children.Add(changeHeight);
            Storyboard.SetTarget(changeHeight, News1);
            Storyboard.SetTargetProperty(changeHeight, new PropertyPath(FrameworkElement.HeightProperty));

            changeOrientation.Duration = TimeSpan.FromSeconds(1);
            changeOrientation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(new System.TimeSpan(0, 0, 1))));
            changeOrientation.FillBehavior = FillBehavior.Stop;
            stb.Children.Add(changeOrientation);
            Storyboard.SetTarget(changeOrientation, News1);
            Storyboard.SetTargetProperty(changeOrientation, new PropertyPath(ScatterViewItem.OrientationProperty));

            stb.Begin(this);

            News1.Center = new Point(250, 400);
            News1.Orientation = 0;
            News1.Width = 266;
            News1.Height = 400;
            Pin1.Visibility = Visibility.Collapsed;
            news1IsOutside = true;
            Scroll1.IsEnabled = true;

它出了什么问题?

2 个答案:

答案 0 :(得分:2)

问题

问题的本质是你正在调用stb.Begin()然后立即更改News1.Width等。不幸的是stb.Begin()不能保证立即启动动画:有时它会在调度员回调。

发生的事情是,第一次执行故事板时,stb.Begin()会调度一个调度程序回调来启动动画并立即返回。接下来的四行代码会更新值:

News1.Center = new Point(250, 400);      
News1.Orientation = 0;      
News1.Width = 266;      
News1.Height = 400;

当动画实际上在调度程序回调中开始时,它们会看到新值并将其用作起始值。这会导致对象看起来立即跳转到新值。

例如,changeWidth声明一个关键帧,将值设置为266:

changeWidth.KeyFrames.Add(new EasingDoubleKeyFrame(266, ...

后来初始宽度设置为266:

News1.Width = 266;

因此,如果故事板开始延迟,宽度将从266到266动画。换句话说,它不会改变。如果您以后使用另一个动画将News1.Width更改为266以外的其他动画,然后运行changeWidth动画,它将起作用。

您的moveCenter动画可靠地运行,因为它实际上将其From值设置为当前值:

moveCenter.From = News1.ActualCenter;    
moveCenter.To = new Point(250, 400);

因此动画总是从旧中心开始,即使动画开始时News1.Center = new Point(250,400)也是如此。

解决方案

就像在PointAnimation上设置“From”一样,您也可以在其他动画中设置初始值。这是通过在时间= 0处添加关键帧来指定当前宽度来完成的:

changeWidth.Duration = TimeSpan.FromSeconds(1);
changeWidth.KeyFrames.Add(new DiscreteDoubleKeyframe(News1.Width, KeyTime.Paced));
changeWidth.KeyFrames.Add(new EasingDoubleKeyFrame(266, KeyTime.Paced));

如果有两个关键帧,此代码使用KeyTime.Paced自动产生0%和100%的事实。实际上,将第一帧设置为KeyFrame.Paced始终等同于KeyTime.FromTimeSpan(TimeSpan.Zero)

答案 1 :(得分:0)

另一个解决方案可能是使用FillBehavior.HoldEnd,然后连接到Storyboard.Completed事件并且:

  • 按原定设置本地值
  • 致电Storyboard.Remove

这样做的好处还在于可以从属性中访问本地值。