动态视觉状态之间的动画,没有特定过渡的爆炸

时间:2011-03-02 14:57:00

标签: silverlight visualstatemanager transitions

我想在Silverlight中尝试实现一个相当简单的场景,但是尽管Silverlight / Blend 4中的所有功能都非常强大,但我还是无法理解如何做到这一点。

我的布局可以归结为:

<UserControl>
    <Grid>
        <StackPanel>
            <Button x:Name="Button1" />
            <Button x:Name="Button2" />
            <Button x:Name="Button3" />
            <Button x:Name="Button4" />
        </StackPanel>
        <Grid x:Name="Page1" />
        <Grid x:Name="Page2" />
        <Grid x:Name="Page3" />
        <Grid x:Name="Page4" />
    </Grid>
</UserControl>

首先,所有四个页面网格都被隐藏并缩放为零大小,但是当您单击其相应的按钮时,该页面应该会显示一个不断增长的动画。当您单击另一个按钮时,上一页应该会随着缩小的动画而消失,而另一个页面应该会显示一个不断增长的动画。通过这种方式,您可以使用按钮在所有四个页面之间进行操作。

根据我的阅读,“正确”的方法是在用户控件上使用视觉状态。所以我创建了四个状态,Page1到Page4,并为每个状态设置了要显示的相应页面网格。然后我在按钮上放置命令以更改用户控件的可视状态。这很好用,我可以在页面之间切换,但是当我开始尝试定义状态之间的动画时,我遇到了问题。

起初,我以为我可以为每个州定义一个'To *'和'From *'动画。所以,当你处于状态Page1,并点击按钮进入状态Page2时,它将播放隐藏Page1的'From *'动画,然后显示Page2的'To *'动画。但这不起作用。即使您为每个州定义了“To *”和“From *”动画,Silverlight也只播放“To *”动画,并完全忽略“From *”动画!

更糟糕的是,似乎这种行为是Silverlight的工作方式,即使它完全没有意义!这意味着如果我想让每个页面缩小,然后另一个页面在其位置增长,我将不得不定义从每个状态到另一个状态的单独转换!对于我目前的四页,这意味着十二个单独的过渡,但是当我想增加页数时,这个数字将会上升。十页需要9 * 9 = 81次转换!全部让当前页面缩小,新页面增长。

我无法相信这没有更好的方法来处理似乎是如此简单的场景,但我找不到任何东西似乎在说明如何。我可以使用修改故事板的代码隐藏来一起破解它,但是我想允许在Blend中查看和编辑页面网格,而且我读到的所有内容都是为了避免使用代码隐藏并使用视图模型和视觉状态来处理事情

请告诉我,我错过了一些明显的东西?

1 个答案:

答案 0 :(得分:3)

在Blend中,您只需单击States选项卡中的状态即可开始状态记录,定义状态应该是什么样的,以及设置状态转换持续时间。

除非您希望每个状态转换排列不同,否则您不必担心每个状态转换排列。

如果您的州使用无法“线性”动画的属性(例如更改“可见性”),请检查FluidLayout按钮。

编辑: 您可以使用每个州仅一个额外的故事板创建您描述的“完全缩小然后增长”效果 - Any - &gt; {State}转换,在生长当前元素之前将BeginTime设置为延迟。

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="CommandingLeakWithScrollbar.UserControl1"
d:DesignWidth="640" d:DesignHeight="480">

<Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1"/>
                <VisualTransition GeneratedDuration="0:0:1" To="Page1">
                    <Storyboard>
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True"/>
                    </Storyboard>
                </VisualTransition>
                <VisualTransition GeneratedDuration="0:0:1" To="Page2">
                    <Storyboard>
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True" />
                        <DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                    </Storyboard>
                </VisualTransition>
                <VisualTransition From="None" GeneratedDuration="0:0:1" To="Page1"/>
                <VisualTransition From="None" GeneratedDuration="0:0:1" To="Page2"/>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="None"/>
            <VisualState x:Name="Page1">
                <Storyboard>
                    <DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                    <DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Page2">
                <Storyboard>
                    <DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                    <DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid x:Name="grid1"  Background="Beige" Width="40" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <Grid x:Name="grid2" HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Top" Background="Wheat" />
    <Grid HorizontalAlignment="Left" Width="40" Height="40" VerticalAlignment="Bottom" />
    <Grid HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Bottom"/>
    <StackPanel HorizontalAlignment="Center">
        <Button Content="Reset" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="None"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Page1" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="Page1"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button Content="Page2" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ei:GoToStateAction StateName="Page2"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </StackPanel>
</Grid>