tags:

views:

27

answers:

2

I am animating an Explorer-style interface, with a Navigator pane on the left and a Workspace on the right. The Navigator displays either a Note List or a Calendar--both are UserControls. Toggle buttons on the app's Ribbon change between the two views. I am animating the change with a dissolve from the old UserControl to the new one.

The animation markup is pretty straightforward and is reproduced in full at the bottom of this post. I declare both user controls, the Calendar first, and then the NoteList, so that the NoteList covers and hides the Calendar. I dissolve from the NoteList to the Calendar by fading out the Note List--animating its Opacity property from 1 to 0, and I dissolve the other way by fading the Note List back in--animating the same property back from 0 to 1:

Dissolve from NoteList to Calendar:

<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />

Dissolve from Calendar to NoteList:

<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />

The animation runs fine, but I discovered that setting the opacity to 0 simply made the Note List control transparent--it still covered the Calendar control, which meant I couldn't click on the Calendar. So, I added a ScaleTransform to each storyboard to get the Note List out of the way when it wasn't showing.

On a dissolve from the NoteList to the Calendar, I ScaleTransform the Note List to 0 after I fade it out to 0:

<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="0" Duration="0:0:0" />

On a dissolve from the Calendar to the NoteList, I ScaleTransform the Note List to 1 before I fade it in to 1:

<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="1" Duration="0:0:0" />
<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />

Here's my problem: When I added the ScaleTransform, it broke the dissolve from the NoteList to the Calendar--the opacity of the Note List went to 0 immediately, instead of over the expected 0.5 second. But the dissolve back from the Calendar to the Note List still works fine--the opacity of the Note List animates from 0 to 1 over the expected 0.5 second.

I tested the problem by commenting out the ScaleTransform declarations, and the animation ran fine again. Uncomment the ScaleTransforms, and the animation is broken again when going from the Note List to the Calendar.

Can anyone suggest why adding the ScaleTransform would break this animation, and in only one direction? Thanks for your help!

--

Here is the animation markup in full:

<ribbon:RibbonToggleButton x:Name="NoteListViewButton" LargeImageSource="Images/ListViewLarge.png" SmallImageSource="Images/ListViewSmall.png" Label="Note List" Click="OnViewButtonClick">
    <ribbon:RibbonToggleButton.Triggers>
        <EventTrigger RoutedEvent="ribbon:RibbonToggleButton.Checked">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="1" Duration="0:0:0" />
                        <DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </ribbon:RibbonToggleButton.Triggers>
</ribbon:RibbonToggleButton>

<ribbon:RibbonToggleButton x:Name="CalendarViewButton" LargeImageSource="Images/CalendarViewLarge.png" SmallImageSource="Images/CalendarViewSmall.png" Label="Calendar" Click="OnViewButtonClick">
    <ribbon:RibbonToggleButton.Triggers>
        <EventTrigger RoutedEvent="ribbon:RibbonToggleButton.Checked">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
                        <DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="0" Duration="0:0:0" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </ribbon:RibbonToggleButton.Triggers>
</ribbon:RibbonToggleButton

>

A: 

Maybe you can overcome the issues with the ScaleTransform by using the StoryBoard.Completed event and set the Visibility of the inactive control to Hidden respectively Collapsed (if there's an appropriate property).

See http://msdn.microsoft.com/en-us/library/system.windows.media.animation.timeline.completed.aspx

Regarding your answer: Have you tried setting the Storyboard.Duration property to 0.5 seconds?

Andreas
Yes, that might work, but it looks like it requires an event handler. I settled on the BeginTime property to hold the ScaleTransform until the Opacity animation was finished.
David Veeneman
A: 

I found my answer. A Storyboard executes all animations simultaneously, so in the case of the dissolve from the NoteList to Calendar, the ScaleTransform was being set to 0 before the Opacity animation ever got a chance to run.

The solution is to set the BeginTime property in the ScaleTransform for the dissolve from the NoteList to the Calendar, to give the Opacity animation time to run. As modified, it looks like this:

<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetName="NoteListControl" Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="0" Duration="0:0:0" BeginTime="0:0:0.5" />

Note the BeginTime property, set to "0:0:0.5", at the end of the second animation declaration. And with that, the animation works!

David Veeneman