Notice that when you use an expander and expand / collapse it that there is a jerkiness depending on the number of elements that you have in it. So to solve this problem you can animate the expand / collapse events that get fired to smoothly open and close. Easy, right?
Well yes and no. You can animate the expanded event pretty easily using the routedEvent "Expander.Expanded" and then apply some transformation that either calculates the height, has a predefined height or (what I like to do) use a layoutTransform and animate the y scale from 0 to 1. Ok ok, that's not terribly hard to accomplish; here's how:
<StackPanel>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Expander.Expanded" SourceName="expander">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0" To="1" Duration="0:0:0.25" Storyboard.TargetName="listBox" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(ScaleTransform.ScaleY)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</StackPanel.Triggers>
<Expander x:Name="expander" Header="Expander">
<ListBox x:Name="listBox">
<ListBoxItem Content="ListBoxItem" />
<ListBoxItem Content="ListBoxItem" />
<ListBoxItem Content="ListBoxItem" />
<ListBox.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="0"/>
</ListBox.LayoutTransform>
</ListBox>
</Expander>
</StackPanel>
Now that works pretty nice, but wait, try to collapse it ... ugly! So we need to do the same thing to the routedEvent "Expander.Collapsed". Hrmm ... on second thought that won't work because the collapsed event sets the expandSites (the expanders content that expands / collapses) visibility to collapsed right away!
So we need to fix this. Here's one approach that overrides the template of the expander and removes the setter that sets the visibility to collapsed. Instead, we are going to animate the layoutTransform on the y scale to 0 for a smooth collapse. We will also do this on the expand event as well, and since we are using the expanders template we will actually be using the IsExpanded property on the expander. This allows us to have a trigger that has enterActions and exitActions so we can easily start off the appropriate animation.
I used Blend to override the template (and thus messy code is produced :) ) and then edited the IsExpanded property appropriately. Attached is the full source code in all xaml that gets the job done. Note 'Timeline1' and 'Timeline2' as they are the storyboards for animating the expanded and collapsed events, respectively. If you have any questions or ways to improve this please let me know!
| Attachment | Size |
|---|---|
| ExpanderAnimateCollapsed.xaml | 19.42 KB |
Mon, 11/10/2008 - 17:22
Hi,
Thanks for providing this code. It is working really well for me at runtime, but at design time the control is not expanded. I have tried to set various things in the ControlTemplate to make it be expanded at design time, with no luck.
Could you offer any suggestions?
Thanks again.
Rich John
Post new comment