Animations between different states of a ListboxItem
I try to implement a ListBox where the selected item is displayed in more detail than the others. One approach is shown by Josh Smith on his blog.
To enhance the user experience, I'd like to animate the change (i.e. the i开发者_C百科tem growing larger, additional information fading in). Using the DataTriggers Enter- or ExitActions to start Storyboard has the disadvandates, that
- I have no reusable template for the detailed view (it just exists as the end state of an animation).
- Every change to the detailed view hs to be worked in at the two animations instead of just once.
Is there another approach thats more easily maintainable?
You could use this ListBox.ItemContainerStyle
and adjust it for your needs.
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border>
<StackPanel>
<ContentPresenter x:Name="Compact"
Opacity="1"
ContentTemplate="{StaticResource UnselectedDataTemplate}">
<ContentPresenter.LayoutTransform>
<ScaleTransform ScaleY="1" />
</ContentPresenter.LayoutTransform>
</ContentPresenter>
<ContentPresenter x:Name="Details"
Opacity="0"
ContentTemplate="{StaticResource SelectedDataTemplate}">
<ContentPresenter.LayoutTransform>
<ScaleTransform ScaleY="0" />
</ContentPresenter.LayoutTransform>
</ContentPresenter>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="SelectionStates">
<VisualState Name="Unselected">
<Storyboard SpeedRatio="2">
<DoubleAnimation To="1"
Storyboard.TargetName="Compact"
Storyboard.TargetProperty="Opacity" />
<DoubleAnimation To="1"
Storyboard.TargetName="Compact"
Storyboard.TargetProperty="LayoutTransform.(ScaleTransform.ScaleY)" />
<DoubleAnimation To="0"
Storyboard.TargetName="Details"
Storyboard.TargetProperty="Opacity" />
<DoubleAnimation To="0"
Storyboard.TargetName="Details"
Storyboard.TargetProperty="LayoutTransform.(ScaleTransform.ScaleY)" />
</Storyboard>
</VisualState>
<VisualState Name="Selected">
<Storyboard SpeedRatio="2">
<DoubleAnimation To="0"
Storyboard.TargetName="Compact"
Storyboard.TargetProperty="Opacity" />
<DoubleAnimation To="0"
Storyboard.TargetName="Compact"
Storyboard.TargetProperty="LayoutTransform.(ScaleTransform.ScaleY)" />
<DoubleAnimation To="1"
Storyboard.TargetName="Details"
Storyboard.TargetProperty="Opacity" />
<DoubleAnimation To="1"
Storyboard.TargetName="Details"
Storyboard.TargetProperty="LayoutTransform.(ScaleTransform.ScaleY)" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In this case I have declared the templates as resources.
<DataTemplate x:Key="UnselectedDataTemplate">
/* your controls for unselected state */
</DataTemplate>
<DataTemplate x:Key="SelectedDataTemplate">
/* your controls for selected state */
</DataTemplate>
But I think binding datatemplated content directly to ContentPresenter.Content
is possible too.
If Details are additional and not for replacement of Compact, simply remove all DoubleAnimation
from Storyboard
with Storyboard.TargetName="Compact"
.
Hope this helps.
精彩评论