Gusdor
Gusdor

Reputation: 14334

VisualStateManager doesn't skip 'non-generated' transitions

The VisualState tools in Blend / WPF / Silverlight are great but I think we can all agree that that are trés buggy on occasion. Here is an example and I would like some clarification / a workaround / fix.

Consider a bunch of visual states defined like this:

<VisualState x:Name="Hidden">
       <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="contentPresenter">
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0">
                    <EasingDoubleKeyFrame.EasingFunction>
                                <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="contentPresenter">
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CircleEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="contentPresenter">
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Revealed">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="contentPresenter">
                                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="contentPresenter">
                                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="contentPresenter">
                                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
                                                <EasingDoubleKeyFrame.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </EasingDoubleKeyFrame.EasingFunction>
                                            </EasingDoubleKeyFrame>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>

Now create a series of trigger to kick switch to these states but select to ignore transition.

The transitions still play. It seems that the visual state manager sees storyboard with more than one contiguous keyframe and plays the whole thing rather than skipping-to-fill when transitions are not used.

The effect I am going for is a 2 stage hide/reveal where the content is faded out and then shrunk. Unfortunately, this means that the state 'transition' will always be played, regardless of my decision to ignore transitions.

Am I being stupid or is this a bug? Is there a workaround?

EDIT - is it better in this case to use an acute easing function to "delay" a transition?

Upvotes: 0

Views: 497

Answers (1)

dtm
dtm

Reputation: 792

The Storyboard declared inside a VisualState is the Storyboard that plays while the VSM is in that state.

The transitions you're talking about ignoring are Storyboards that play while transitioning from VisualState to VisualState. These are specified separately in a VisualStateGroup.Transitions section.

So, something like:

<VisualStateGroup x:Name="Something">
    <VisualState x:Name="Hidden">
    <VisualState x:Name="Revealed">

    <VisualStateGroup.Transitions>
        <VisualTransition From="Hidden" To="Revealed">
            <Storyboard>
                ...
            <Storyboard>
        </VisualTransition>
        <VisualTransition From="Revealed" To="Hidden">
            <Storyboard>
                ...
            <Storyboard>
        </VisualTransition>
    </VisualStateGroup.Transitions>
</VisualStateGroup>

And fill in the appropriate animations inside the Storyboards.

After this, when you pass in false to the useTransitions parameter of the VisualStateManager's GoToState or GoToElementState methods, you won't see the transitions.

Upvotes: 2

Related Questions