我写了以下代码。它尝试创建一个执行以下操作的故事板:
但是在运行时获取System.InvalidOperationException,后跟以下输出:
Additional information: Multiple animations in
the same containing Storyboard cannot target the
same property on a single element.
这似乎表明它试图一次完成所有动画而不是顺序动画。
private Storyboard createStoryboard()
{
Storyboard board = new Storyboard();
addFadeToStoryboard(board, 0, 1, 500);
addFadeToStoryboard(board, 1, 1, 1000);
DoubleAnimation fadeOut = addFadeToStoryboard(board, 1, 0, 500);
fadeOut.Completed += new EventHandler(onFadeCompleted);
Storyboard.SetTarget(board, this);
return board;
}
private DoubleAnimation addFadeToStoryboard(Storyboard board,
double fadeFrom, double fadeTo, double milliseconds)
{
DoubleAnimation fade = new DoubleAnimation()
{
Duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)),
From = fadeFrom,
To = fadeTo,
RepeatBehavior = new RepeatBehavior(1)
};
Storyboard.SetTargetProperty(fade,
new PropertyPath(UIElement.OpacityProperty));
board.Children.Add(fade);
return fade;
}
如何使其顺序?我是否误解了故事板的基本内容?
由于
答案 0 :(得分:3)
如果故事板包含多个动画,则它们全部同时启动并同时运行。您可以将DoubleAnimations上的BeginTime属性设置为TimeSpan以指示它们应该何时开始...因此,通过传入所有先前动画的累积时间,您应该能够获得连续效果。
编辑:抱歉 - 我刚注意到了Silverlight标签。我的答案适用于WPF ...我不知道Silverlight和WPF动画之间的区别。This可能有所帮助。它看起来像是WPF和Silverlight之间的区别。 WPF可以在同一个故事板中处理不同动画上的相同属性的动画,而Silverlight则不然。他们建议使用单个DoubleAnimationUsingKeyFrames而不是单独的DoubleAnimations ...然后每个单独的动画成为其中的关键帧,它应该在它们之间线性动画。
答案 1 :(得分:0)
我通过创建自己的音序器类来解决这个问题。它依赖于LinkedList类,因此如果要使用此代码,则必须将其与标准类交换:
using System;
using System.Windows.Media.Animation;
namespace YourNamespace
{
// An object that contains multiple storyboards, and fires off
// subsequent ones as they finish.
public class StoryboardSequencer
{
public StoryboardSequencer()
{
}
public void add(Storyboard board)
{
m_boards.add(board);
board.Completed += new EventHandler(onBoardCompleted);
}
// Starts the storyboard from the first.
// If already started, this call is ignored.
public void begin()
{
if (m_boards.size() > 0)
{
m_currentBoardIndex = 0;
beginCurrentBoard();
}
else
{
onLastBoardCompleted();
}
}
// Stops and rewinds.
// Does not call completed handler.
public void stop()
{
if (m_currentBoardIndex != -1)
{
Storyboard board = m_boards.get(m_currentBoardIndex);
if (board != null)
{
board.Stop();
}
m_currentBoardIndex = -1;
}
}
private void beginCurrentBoard()
{
Storyboard board = m_boards.get(m_currentBoardIndex);
if (board == null)
{
onLastBoardCompleted();
}
else
{
board.Begin();
}
}
// Triggered when the sequence completes.
public event EventHandler Completed;
private void onBoardCompleted(object sender, EventArgs e)
{
m_currentBoardIndex++;
if (m_currentBoardIndex >= m_boards.size())
{
onLastBoardCompleted();
}
else
{
beginCurrentBoard();
}
}
private void onLastBoardCompleted()
{
m_currentBoardIndex = -1;
Completed.Invoke(this, null);
}
private LinkedList<Storyboard> m_boards = new LinkedList<Storyboard>();
// The current storyboard playing, or -1 if none.
private int m_currentBoardIndex = -1;
}
}