2010-06-14 101 views
1

我正在做一个表面应用程序。 在那里我有一个像公告板一样的地方,里面贴着新闻的小卡片。 点击后,他们应该飞出董事会并扩大规模。 我的故事板运行良好,除了第一次运行。这不是一个平滑的动画,但它立即缩放到最终大小,这与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; 

这有什么错呢?

回答

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动画作品可靠,因为它实际上将其从值与当前值:即使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)

+0

那么,需要让你困惑的一点是: 当我只是做正常的故事板,你无法移动scatterviewsitems(我忘了​​告诉你,他们是scatterviewitems,我想,我很抱歉。 ..)稍后。他们被困在他们的位置上。 所以我不得不添加“changeHeight.FillBehavior = FillBehavior.Stop;”。 但现在又出现了另一个问题: 项目跳回到它们来自的地方。 所以我不得不添加“News1.Center =新点(250,400);”的东西。 而这些并不是他们开始的观点。他们从其他价值观开始。 我有第二个故事板,相反。 – sofri 2010-06-16 06:39:18

+0

因此,我第一次点击该项目,它跳出来,第二次点击将使它跳回到公告板。 所以它运作良好,但不是第一次点击它。除了它跳出来,就像它应该。 希望我能更好地解释这一次;) – sofri 2010-06-16 06:41:50

+0

谢谢。现在我更好地理解了这个问题。我已经重写了我的答案,以解释发生了什么以及如何解决它。 – 2010-06-16 16:43:27

0

另一种解决办法可能是使用FillBehavior.HoldEnd,然后勾到Storyboard.Completed事件:

  • 设置本地值,你本来
  • 呼叫Storyboard.Remove

这也将有从属性可以访问本地值的优点。

相关问题