在Windows Phone应用中重复使用故事板

3

我有一个在我的Windows Phone应用中使用的Storyboard

<Canvas x:Name="myCanvas" Grid.Row="1">
  <Canvas.Resources>
    <Storyboard x:Name="sb">
      <ColorAnimationUsingKeyFrames 
             Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
             AutoReverse="True">
               <EasingColorKeyFrame KeyTime="00:00:0" Value="Black" />
               <EasingColorKeyFrame KeyTime="00:00:0.25" Value="Red" />
      </ColorAnimationUsingKeyFrames>
    </Storyboard>
  </Canvas.Resources>
</Canvas>

我有多个Rectangle将使用此Storyboard,但似乎只有第一次有效。
例如,以下代码用于显示四个不同的Rectangles,但只显示第一个。代码没有出错,但最后3个Rectangle没有变红,而且似乎Storyboard甚至没有运行。
sb.Stop();
sb.SetValue(Storyboard.TargetNameProperty, myRect1.name);
sb.Begin();

sb.Stop();
sb.SetValue(Storyboard.TargetNameProperty, myRect2.name);
sb.Begin();

sb.Stop();
sb.SetValue(Storyboard.TargetNameProperty, myRect3.name);
sb.Begin();

sb.Stop();
sb.SetValue(Storyboard.TargetNameProperty, myRect4.name);
sb.Begin();

有谁能发现我做错了什么,或者知道如何使我的Storyboard可重用?

2个回答

2

首先,你做错的事情:

故事板执行是异步的。当你调用 Storyboard.Begin 方法时,故事板开始在后台执行,而你的代码继续执行。因此,你在启动它后立即调用了 Storyboard.Stop!唯一不停止的是最后一个,这就是为什么只有最后一个矩形的颜色会改变。

如果你想要链接你的动画,你需要订阅 Completed 事件以知道故事板何时结束,然后重新启动它以用于下一个控件。以下是一种实现方式:

private Rectangle[] ControlsToAnimate;

private int CurrentIndex;

private void Button_Click(object sender, RoutedEventArgs e)
{
    this.ControlsToAnimate = new[] { this.Rectangle1, this.Rectangle2 };

    this.Storyboard1.Completed += StoryboardCompleted;
    this.AnimateNextControl();
}

private void AnimateNextControl()
{
    if (this.CurrentIndex >= this.ControlsToAnimate.Length)
    {
        this.CurrentIndex = 0;
        return;
    }

    var nextControl = this.ControlsToAnimate[this.CurrentIndex];

    this.CurrentIndex++;

    this.Storyboard1.Stop();
    this.Storyboard1.SetValue(Storyboard.TargetNameProperty, nextControl.Name);
    this.Storyboard1.Begin();
}

private void StoryboardCompleted(object sender, EventArgs e)
{
    this.AnimateNextControl();
}

现在,您将面临两个问题:

  1. When assigning the storyboard to a new control, the color of the previous control will return to its original value (before the storyboard was started). If you want it to keep its new value, you've got to save it:

    private void AnimateNextControl()
    {
        if (this.CurrentIndex > 0)
        {
            var brush = (SolidColorBrush)this.ControlsToAnimate[this.CurrentIndex - 1].Fill;
            brush.Color = brush.Color;
        }
    
        if (this.CurrentIndex >= this.ControlsToAnimate.Length)
        {
            this.CurrentIndex = 0;
            return;
        }
    
        var nextControl = this.ControlsToAnimate[this.CurrentIndex];
    
        this.CurrentIndex++;
    
        this.Storyboard1.Stop();
        this.Storyboard1.SetValue(Storyboard.TargetNameProperty, nextControl.Name);
        this.Storyboard1.Begin();
    }
    
  2. You can't animate two controls at the same time using a single storyboard. If you want to animate all your rectangles at the same time, you need to use one storyboard per control.


谢谢!至于我将面临的问题,前一个控件的颜色在开始下一个故事板之前恢复正常是完全可以接受的。我只想把它变成红色,然后再变成黑色。我也不需要使用此故事板同时动画两个控件。我将尝试使用您的示例,并使用“Completed”事件。 - lhan
是的,这似乎是我需要的。再次感谢! - lhan

1

我必须再次将我的评论作为答案,因为显然我仍然无法发表评论。

您是否尝试同时运行它们?我相信只有一个XAML定义的故事板实例存在,因此您可能无法同时在多个控件上重用它。

如果一切都失败了,您可以创建一个包含故事板的矩形的UserControl,您可以在其中重复使用它。我在您之前的问题中提供的代码示例是使用故事板翻转的Tile。由于它是一个用户控件,我可以同时拥有任意数量的翻转瓷砖。


不需要同时运行它们。 - lhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接