Wpf treeview - i want to animate the expansion of

2019-06-14 16:03发布

问题:

I have a databound treeview that i want to animate when the nodes are expanded. The animation should work vertically. Any ideas on how I could do that?

回答1:

Download default style for treeview and apply it to your treeview control, then change/add this xaml code to the treeview style:

<!-- change item presenter to include a layout transform -->
<ItemsPresenter x:Name="ItemsHost">
 <ItemsPresenter.LayoutTransform>
  <ScaleTransform ScaleY="1" />
 </ItemsPresenter.LayoutTransform>
</ItemsPresenter>

<!-- Add this to control template triggers -->
<Trigger Property="IsExpanded" Value="true"> 
 <Trigger.EnterActions>
  <BeginStoryboard>
   <Storyboard>
   <DoubleAnimation Storyboard.TargetName="ItemsHost"
     Storyboard.TargetProperty="LayoutTransform.ScaleY"
     To="1"
     Duration="0:0:0.3" />
   <DoubleAnimation Storyboard.TargetName="ItemsHost"
     Storyboard.TargetProperty="Opacity"
     To="1"
     Duration="0:0:0.5" />    
   </Storyboard>
  </BeginStoryboard>
 </Trigger.EnterActions>

 <Trigger.ExitActions>
  <BeginStoryboard>
   <Storyboard>
   <DoubleAnimation Storyboard.TargetName="ItemsHost"
     Storyboard.TargetProperty="LayoutTransform.ScaleY"
     To="0"
     Duration="0:0:0.3" />
   <DoubleAnimation Storyboard.TargetName="ItemsHost"
     Storyboard.TargetProperty="Opacity"
     To="0"
     Duration="0:0:0.5" />    
  </Storyboard>
  </BeginStoryboard>
 </Trigger.ExitActions>    
</Trigger>  


<!-- comment this code -->
<!--Setter TargetName="ItemsHost"
   Property="Visibility"
   Value="Collapsed"/-->


回答2:

Get the original template of TreeViewItem and modify it to have the animation. Then install it thanks to the ItemContainerStyle of TreeView.



回答3:

I think this is'n a solution because you need the tirgger

<Trigger Property="IsExpanded" Value="false"> 
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
</Trigger>

else you get a tree with open all branch and the animation doesn't work correctly.



回答4:

@user275587's post, it needs to modify the original TreeViewItem style. After google, I found some styles at MSDN.

  • The TreeViewItem style I found at the MSDN.

Update:

The custom TreeViewItem style with animation effection in ResourceDictionary file. It is modified by the TreeViewItem style in MSDN, and the posts of @user275587 and @icube.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="GlyphBrush" Color="#444" />
<!--
    =================================================================
    TreeViewItem
    ==================================================================
-->
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
    <Setter Property="Focusable" Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Grid Width="15"
                      Height="13"
                      Background="Transparent">
                    <Path x:Name="ExpandPath"
                          Margin="1,1,1,1"
                          HorizontalAlignment="Left"
                          VerticalAlignment="Center"
                          Data="M 4 0 L 8 4 L 4 8 Z"
                          Fill="{StaticResource GlyphBrush}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="ExpandPath" Property="Data" Value="M 0 4 L 8 4 L 4 8 Z" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="TreeViewItemFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Border>
                    <Rectangle Margin="0,0,0,0"
                               Opacity="0"
                               Stroke="Black"
                               StrokeDashArray="1 2"
                               StrokeThickness="5" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="customTreeViewItem" TargetType="{x:Type TreeViewItem}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
    <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
    <Setter Property="Padding" Value="1,0,0,0" />
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
    <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" MinWidth="19" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <ToggleButton x:Name="Expander"
                                  ClickMode="Press"
                                  IsChecked="{Binding Path=IsExpanded,
                                                      RelativeSource={RelativeSource TemplatedParent}}"
                                  Style="{StaticResource ExpandCollapseToggleStyle}" />
                    <Border Name="Bd"
                            Grid.Column="1"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}">
                        <ContentPresenter x:Name="PART_Header"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          ContentSource="Header" />
                    </Border>
                    <ItemsPresenter x:Name="ItemsHost"
                                    Grid.Row="1"
                                    Grid.Column="1"
                                    Grid.ColumnSpan="2">
                        <ItemsPresenter.LayoutTransform>
                            <ScaleTransform ScaleY="1" />
                        </ItemsPresenter.LayoutTransform>
                    </ItemsPresenter>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="false">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.3"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="LayoutTransform.ScaleY"
                                                     To="0" />
                                    <DoubleAnimation Duration="0:0:0.5"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="0" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.3"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="LayoutTransform.ScaleY"
                                                     To="1" />
                                    <DoubleAnimation Duration="0:0:0.5"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="1" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                    <Trigger Property="IsExpanded" Value="true">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.3"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="LayoutTransform.ScaleY"
                                                     To="1" />
                                    <DoubleAnimation Duration="0:0:0.5"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="1" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>

                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.3"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="LayoutTransform.ScaleY"
                                                     To="0" />
                                    <DoubleAnimation Duration="0:0:0.5"
                                                     Storyboard.TargetName="ItemsHost"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="0" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false" />
                            <Condition Property="Width" Value="Auto" />
                        </MultiTrigger.Conditions>
                        <Setter TargetName="PART_Header" Property="MinWidth" Value="75" />
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false" />
                            <Condition Property="Height" Value="Auto" />
                        </MultiTrigger.Conditions>
                        <Setter TargetName="PART_Header" Property="MinHeight" Value="19" />
                    </MultiTrigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true" />
                            <Condition Property="IsSelectionActive" Value="false" />
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And I decorate my treeViewItem it by inherit the customTreeViewItem style. The following is sample code.

<TreeView.ItemContainerStyle>
                <Style BasedOn="{StaticResource customTreeViewItem}" TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                    <Setter Property="FontWeight" Value="Normal" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TreeView.ItemContainerStyle>