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

WPF故事板运行良好,除了第一次运行。为什么?,wpf,Wpf,我在做表面处理。 在那里我有一个类似于公告板的东西,上面钉着新闻的小卡片。 点击后,它们将飞出棋盘并放大。 我的故事板运行良好,除了第一次运行。这不是一个平滑的动画,但它会立即缩放到最终大小,并且方向属性也是如此。只有“中心”属性的行为似乎正确 这是我的一个故事板的一个例子: Storyboard stb = new Storyboard(); PointAnimation moveCenter = new PointAnimation();

我在做表面处理。 在那里我有一个类似于公告板的东西,上面钉着新闻的小卡片。 点击后,它们将飞出棋盘并放大。 我的故事板运行良好,除了第一次运行。这不是一个平滑的动画,但它会立即缩放到最终大小,并且方向属性也是如此。只有“中心”属性的行为似乎正确

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

            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;

有什么问题吗?

问题

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

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

News1.Center = new Point(250, 400);      
News1.Orientation = 0;      
News1.Width = 266;      
News1.Height = 400;
当动画在dispatcher回调中实际启动时,它们会看到新值并将其用作起始值。这会导致对象立即跳转到新值

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

changeWidth.KeyFrames.Add(new EasingDoubleKeyFrame(266, ...
之后,初始宽度设置为266:

News1.Width = 266;
因此,如果故事板延迟启动,宽度将从266设置为266。换句话说,它不会改变。如果以后使用另一个动画将News1.Width更改为266以外的值,然后运行changeWidth动画,则该动画将正常工作

移动中心动画工作可靠,因为它实际上将其“从”值设置为当前值:

moveCenter.From = News1.ActualCenter;    
moveCenter.To = new Point(250, 400);
因此,动画始终从旧中心开始,即使动画开始后,
News1.center=new Point(250400)

解决方案

正如在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)
另一种解决方案可能是使用
FillBehavior.HoldEnd
,然后连接到
情节提要。已完成
事件和:

  • 像最初那样设置本地值
  • 调用故事板。删除

这还有一个优点,就是可以从属性中访问本地值。

好吧,有一点让您感到困惑:当我只是做普通的故事板时,您无法移动散点视图站点(我想我忘了告诉您它们是散点视图项。很抱歉…)稍后。他们被困在原地。所以我不得不添加“changehight.FillBehavior=FillBehavior.Stop;”。但现在又出现了另一个问题:物品跳回了它们的来源。所以我不得不添加“News1.Center=newpoint(250400);”之类的东西。而这并不是他们的出发点。他们从其他价值观开始。我有第二个故事板,正好相反。所以我第一次点击这个项目,它会跳出,第二次点击会使它跳回公告板。所以它工作得很好,但这不是你第一次点击它。除了它应该跳出来跳回来。希望这次我能解释得更好;)谢谢现在我更了解这个问题了。我已经重写了我的答案,解释发生了什么以及如何解决它。