WPF - 如何在StackPanel方向改变时添加动画效果?

10

我想创建一个动画,使一个图标(一个包含在Viewbox中的XAML矢量图形)从旁边有文本(TextBlock)变为下方有文本。

我目前将Viewbox和TextBlock放在一个水平方向的StackPanel中。我可以将方向更改为垂直方向,但这是一个瞬时变化(无法平滑动画化)。我也可以使用TranslateTransform来设置TextBlock的位置(可以进行动画处理),但这种方式难以以可重复使用的方式实现(即不硬编码值)。

请问是否有任何以WPF为中心的方法可以动画化从水平到垂直方向在stack-panel中的转换?或者还有其他我没有考虑到的方法可以实现所需的效果吗?

谢谢大家!


我的直觉告诉我您需要编写一些代码来进行一些翻译转换,而且这不会很美观。看看是否有人能想出一个好的方法会很有趣。 - Ray
你是想将它放置在相对于ViewBox的某个特定区域吗?例如,无论ViewBox的大小如何,您始终可以将其放置在ViewBox的左侧和下方...? - Aaron McIver
它可能无法达到“期望的效果”,但一种更平滑的动画方式可能会更简单,即在更改 StackPanel 的方向时淡出文本,然后再淡入文本(例如使用 DataTrigger 和其 Start-/EndActions,虽然我不知道你能否轻松地控制时序...) - Dan J
1个回答

5

Blend中有一个名为FluidLayout的功能可以实现此操作。

在Blend中

  • 创建一个新的状态组,设置过渡持续时间并启用流式布局。
  • 创建两个状态,一个水平,一个垂直。
  • 然后可以使用行为在它们之间切换。

如果您没有Blend,则可以下载SDK,其中应该包含所需的文件Microsoft.Expression.Interactions和System.Windows.Interactivity。添加对这些文件的引用并尝试下面的示例。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:il="clr-namespace:Microsoft.Expression.Interactivity.Layout;assembly=Microsoft.Expression.Interactions"
    xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
    x:Class="WpfApplication4.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">

    <Grid x:Name="LayoutRoot">
        <VisualStateManager.CustomVisualStateManager>
            <ic:ExtendedVisualStateManager/>
        </VisualStateManager.CustomVisualStateManager>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="Orientation" ic:ExtendedVisualStateManager.UseFluidLayout="True">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="00:00:00.3000000"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Vertical"/>
                <VisualState x:Name="Horizontal">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="stack" Storyboard.TargetProperty="(StackPanel.Orientation)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Orientation.Horizontal}"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <StackPanel x:Name="stack" Margin="8,49,8,8">
            <Button Content="Button"/>
            <Button Content="Button"/>
            <Button Content="Button"/>
            <Button Content="Button"/>
            <Button Content="Button"/>
        </StackPanel>
        <Button HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="97" Height="25" Content="H">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ic:GoToStateAction StateName="Horizontal"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button HorizontalAlignment="Left" Margin="109,8,0,0" VerticalAlignment="Top" Width="97" Height="25" Content="V">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <ic:GoToStateAction StateName="Vertical"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
</Window>

你可以使用类似的方法来处理项目转换,使用状态移动元素或通过更改Grid.Row、RowSpan、Col。您可能需要一些代码来将所有内容绑定在一起。我正在查看一个更为详细的示例,如果我解决了问题,就会发布它。

这看起来是一个非常好的方法。+1 - Rob Perkins
最终我只能通过手动为画布上的元素创建动画来实现这种效果。我们的项目团队没有使用Blend,因此fluidlayout不是一个选择。 - Nick W.
@Nick W.:如果您最终自己找到了问题的答案,请将其作为实际答案添加到问题中并接受它(可能还会向那些可以使用 Blend 的人提供此答案的参考)。 - H.B.

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