Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - Animating a change in orientation of a stackpanel?

I'm trying to create an animation where an icon (a xaml vector graphic on a Viewbox-wrapped Canvas) goes from having its text (TextBlock) beside it to underneath it.

I currently have the Viewbox and TextBlock in a Horizontally oriented StackPanel. I can change the orientation to vertical, but this is an instant change (not smoothly animated). I can also just set the position of the TextBlock with a TranslateTransform (which can be animated), but this is difficult to do in a reusable way (i.e. without hard-coding values).

Can anyone tell me if there is any WPF-centric way to animate the transition from horizontal to vertical orientation in a stack-panel? Or another way I haven't thought of to achieve the desired effect?

Thanks all!

like image 364
Nick W. Avatar asked Jan 31 '11 00:01

Nick W.


1 Answers

There is a feature in Blend called FluidLayout that can do this.

In Blend

  • Create a new state group, set a transition duration and enable fluid layout.
  • Create two states one for horizontal, one for vertical.
  • You can then use a behaviour to toggle between them.

If you don't have Blend you can download the SDK which should have the required files Microsoft.Expression.Interactions and System.Windows.Interactivity. Add references to these and try the sample below.

<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>

You can use a similar method to handle the item transition using states to move the elements or by changing Grid.Row,RowSpan,Col. You may need some code to tie everything together. I'm looking at a more elaborate sample I'll post if I sort out the issues.

like image 136
Kris Avatar answered Nov 07 '22 00:11

Kris