WPF Storyboard运行良好,除了第一次运行。为什么?
我正在做一个表面应用程序。 在那里我有一个像公告板一样的地方,里面贴着新闻的小卡片。 点击后,他们应该飞出董事会并扩大规模。 我的故事板运行良好,除了第一次运行。这不是一个平滑的动画,但它立即缩放到最终大小,这与orientation-property一样。只是中心属性似乎表现正确。WPF Storyboard运行良好,除了第一次运行。为什么?
这是我的故事板的一个例子这样做:
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;
当动画中,他们看到了新的价值观调度回调真正开始,并使用这些作为自己的初始值。这会导致对象立即跳转到新值。
例如,changeWidth声明动画的值以266关键帧:
changeWidth.KeyFrames.Add(new EasingDoubleKeyFrame(266, ...
和后来的初始宽度被设定为266:
News1.Width = 266;
因此,如果故事板被延迟起动,宽度将从266增加到266.也就是说,它不会改变。如果以后使用另一个动画将News1.Width更改为266以外的内容,然后运行changeWidth动画,则该动画将起作用。
你moveCenter动画作品可靠,因为它实际上将其从值与当前值:即使News1.Center = new Point(250,400)
一旦动画开始
moveCenter.From = News1.ActualCenter;
moveCenter.To = new Point(250, 400);
因此,动画总是开始于老中心。
解决方案
正如您将“从”您PointAnimation,你还可以设置你的其他动画的初始值。这是通过在时间= 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
,然后勾到Storyboard.Completed
事件:
- 设置本地值,你本来
- 呼叫
Storyboard.Remove
这也将有从属性可以访问本地值的优点。
那么,需要让你困惑的一点是: 当我只是做正常的故事板,你无法移动scatterviewsitems(我忘了告诉你,他们是scatterviewitems,我想,我很抱歉。 ..)稍后。他们被困在他们的位置上。 所以我不得不添加“changeHeight.FillBehavior = FillBehavior.Stop;”。 但现在又出现了另一个问题: 项目跳回到它们来自的地方。 所以我不得不添加“News1.Center =新点(250,400);”的东西。 而这些并不是他们开始的观点。他们从其他价值观开始。 我有第二个故事板,相反。 – sofri 2010-06-16 06:39:18
因此,我第一次点击该项目,它跳出来,第二次点击将使它跳回到公告板。 所以它运作良好,但不是第一次点击它。除了它跳出来,就像它应该。 希望我能更好地解释这一次;) – sofri 2010-06-16 06:41:50
谢谢。现在我更好地理解了这个问题。我已经重写了我的答案,以解释发生了什么以及如何解决它。 – 2010-06-16 16:43:27