在另一个故事板的时间轴内启动故事板。

4
我有一个故事板(1),它在2秒钟内进行一些基本动画。我希望这个故事板(1)能够执行我设置好的所有属性动画(这一切都很正常)。但是在故事板(1)运行到3秒时,我想启动故事板(2),并且完全不需要用户交互就退出故事板(1)。
我只看到当用户点击某些东西时才允许我这样做。我希望根据当前故事板(1)时间轴的位置自动完成此操作。
我希望这足够清楚。如果您需要更详细的解释,请告诉我。
谢谢。
编辑:请用XAML或VB.net语言发布答案。 :)
3个回答

7
通常在时间轴上控制动画,需要使用“关键帧”。关键帧动画允许您在特定时间为正在动画化的属性定义特定值。在WPF中,每个动画都有相应的关键帧动画,例如“DoubleAnimation”具有“DoubleAnimationUsingKeyFrames”。
我认为不可能在动画中启动新的故事板。但是,您可以通过将两个故事板放置在同一时间轴上,并根据故事板(1)的持续时间,延迟特定时间来启动故事板(2)来实现相同的结果。类似于:
<StackPanel>
    <Rectangle Name="recProgressBar"
               Fill="Orange"
               Width="1"
               Height="25"
               Margin="20"
               HorizontalAlignment="Left" />
    <Button Content="Start Animation"
            Width="150"
            Height="25">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="recProgressBar"
                                         Storyboard.TargetProperty="Width"
                                         From="0"
                                         To="250"
                                         Duration="0:0:2" />
                        <Storyboard BeginTime="0:0:3">
                            <ColorAnimation Storyboard.TargetName="recProgressBar"
                                            Storyboard.TargetProperty="Fill.Color"
                                            To="DarkGreen"
                                            Duration="0:0:1" />
                        </Storyboard>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>
</StackPanel>
在这里,颜色动画将在宽度动画完成后1秒钟开始。这值得一试。

0

谢谢Megakemp,这正是我担心的事情。我不想在XAML中管理两个故事板的副本。如果我必须添加一个控件并通过故事板(1)进行管理,我将不得不记住将更改复制并粘贴到另一个故事板(2)中。我想这些都是你必须跳过的障碍,直到我正在寻找的功能出现。

现在我想到了另一个想法,但无法获得功能。以下是我的想法,我可以用代码更好地解释它。下面的代码将无法编译,只是为了表达我的观点。

Dim board As Storyboard = New Storyboard
board = DirectCast(TryFindResource("Animation1"), Storyboard)
If board IsNot Nothing Then
    board.Begin(Me)
    While board.GetCurrentState(Me) = ClockState.Active
        'Wait until Animation1 ends
    End While
    'Start Animation2
    board = DirectCast(TryFindResource("Animation2"), Storyboard)
    If board IsNot Nothing Then
        board.Begin(Me)
    End If
End If

感谢您的帮助。如果还有其他答案或更多见解,请不要犹豫发表,我还没有完全放弃这个想法。


你不需要管理两份副本,只需将storyboard作为资源使用并引用两次即可! - Bob King
启动延迟设置在Storyboard对象本身上,因此他需要有两个副本,一个带有延迟,一个没有。 - Enrico Campidoglio
Bob King,请提供一个你的解决方案的例子,这样我就能更好地理解你在说什么。Megakemp,你和我的思路是一致的。 - ScottN

0

好的,我想到了一个解决方法。我刚刚生成了一个新线程,等待3秒钟,然后通过Invoke调用从该线程运行Storyboard。

    Dim board As Storyboard = New Storyboard
    board = DirectCast(TryFindResource("DoSplit"), Storyboard)
    If board IsNot Nothing Then
        board.Begin(Me, True)

        Dim t As Thread
        t = New Thread(AddressOf Me.WaitToHidePanel)
        t.SetApartmentState(ApartmentState.STA)
        t.Start()

    End If

将你的委托和函数变成线程安全的,这样就可以让它正常工作了。在我看来,这是一种丑陋的hack方法,但现在它能够工作。


是的,当你无法在XAML中100%解决UI问题,而不得不使用命令式代码时,总是很遗憾。 - Enrico Campidoglio

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