Animate Expander in WPF

后端 未结 2 1689
予麋鹿
予麋鹿 2020-12-10 01:02

How to animate the expanded and collapsed actions of a Wpf expander control?

相关标签:
2条回答
  • 2020-12-10 01:33

    I've found this article on Code Project : Read Here

    The author creates his own SimpleExpander Template, then adds a stretch out animation to it. He even added a nifty rotating arrow to it.

    0 讨论(0)
  • 2020-12-10 01:34

    I created a style based on msdn Style and the point in this answer:

     <Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Test" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        mc:Ignorable="d">
    
    <Window.Resources>
        <Color x:Key="WindowColor">#FFE8EDF9</Color>
        <Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
        <Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
    
        <Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
        <Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
        <Color x:Key="DisabledForegroundColor">#FF888888</Color>
    
        <Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
        <Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
    
        <Color x:Key="ControlLightColor">White</Color>
        <Color x:Key="ControlMediumColor">#FF7381F9</Color>
        <Color x:Key="ControlDarkColor">#FF211AA9</Color>
    
        <Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
        <Color x:Key="ControlPressedColor">#FF211AA9</Color>
    
    
        <Color x:Key="GlyphColor">#FF444444</Color>
        <Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>
    
        <!--Border colors-->
        <Color x:Key="BorderLightColor">#FFCCCCCC</Color>
        <Color x:Key="BorderMediumColor">#FF888888</Color>
        <Color x:Key="BorderDarkColor">#FF444444</Color>
    
        <Color x:Key="PressedBorderLightColor">#FF888888</Color>
        <Color x:Key="PressedBorderDarkColor">#FF444444</Color>
    
        <Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
        <Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
    
        <Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
    
        <!--Control-specific resources.-->
        <Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
        <Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
        <Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
    
        <Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
    
        <LinearGradientBrush x:Key="MenuPopupBrush"
                       EndPoint="0.5,1"
                       StartPoint="0.5,0">
            <GradientStop Color="{DynamicResource ControlLightColor}"
                  Offset="0" />
            <GradientStop Color="{DynamicResource ControlMediumColor}"
                  Offset="0.5" />
            <GradientStop Color="{DynamicResource ControlLightColor}"
                  Offset="1" />
        </LinearGradientBrush>
    
        <LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
                       StartPoint="0,0"
                       EndPoint="1,0">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#000000FF"
                      Offset="0" />
                    <GradientStop Color="#600000FF"
                      Offset="0.4" />
                    <GradientStop Color="#600000FF"
                      Offset="0.6" />
                    <GradientStop Color="#000000FF"
                      Offset="1" />
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    
        <ControlTemplate x:Key="ExpanderToggleButton"
                   TargetType="{x:Type ToggleButton}">
            <Border x:Name="Border"
            CornerRadius="2,0,0,0"
            BorderThickness="0,0,1,0">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1"
                             StartPoint="0.5,0">
                        <GradientStop Color="{DynamicResource ControlLightColor}" />
                        <GradientStop Color="{DynamicResource ControlMediumColor}"
                        Offset="1" />
                    </LinearGradientBrush>
                </Border.Background>
                <Border.BorderBrush>
                    <LinearGradientBrush StartPoint="0,0"
                             EndPoint="0,1">
                        <LinearGradientBrush.GradientStops>
                            <GradientStopCollection>
                                <GradientStop Color="{DynamicResource BorderLightColor}"
                            Offset="0.0" />
                                <GradientStop Color="{DynamicResource BorderDarkColor}"
                            Offset="1.0" />
                            </GradientStopCollection>
                        </LinearGradientBrush.GradientStops>
                    </LinearGradientBrush>
    
                </Border.BorderBrush>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                            Storyboard.TargetProperty="(Panel.Background).
                  (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                    <EasingColorKeyFrame KeyTime="0"
                                     Value="{StaticResource ControlMouseOverColor}" />
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                            Storyboard.TargetProperty="(Panel.Background).
                  (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                    <EasingColorKeyFrame KeyTime="0"
                                     Value="{StaticResource ControlPressedColor}" />
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                            Storyboard.TargetProperty="(Panel.Background).
                  (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                    <EasingColorKeyFrame KeyTime="0"
                                     Value="{StaticResource DisabledControlDarkColor}" />
                                </ColorAnimationUsingKeyFrames>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                            Storyboard.TargetProperty="(Border.BorderBrush).
                  (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                    <EasingColorKeyFrame KeyTime="0"
                                     Value="{StaticResource DisabledBorderLightColor}" />
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="CheckStates">
                        <VisualState x:Name="Checked">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                             Storyboard.TargetName="CollapsedArrow">
                                    <DiscreteObjectKeyFrame KeyTime="0"
                                        Value="{x:Static Visibility.Hidden}" />
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                             Storyboard.TargetName="ExpandededArrow">
                                    <DiscreteObjectKeyFrame KeyTime="0"
                                        Value="{x:Static Visibility.Visible}" />
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Unchecked" />
                        <VisualState x:Name="Indeterminate" />
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Grid>
                    <Path x:Name="CollapsedArrow"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Data="M 0 0 L 4 4 L 8 0 Z">
                        <Path.Fill>
                            <SolidColorBrush Color="{DynamicResource GlyphColor}" />
                        </Path.Fill>
                    </Path>
                    <Path x:Name="ExpandededArrow"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Visibility="Collapsed"
              Data="M 0 4 L 4 0 L 8 4 Z">
                        <Path.Fill>
                            <SolidColorBrush Color="{DynamicResource GlyphColor}" />
                        </Path.Fill>
                    </Path>
                </Grid>
            </Border>
        </ControlTemplate>
    
        <Style TargetType="{x:Type Expander}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Expander}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition x:Name="ContentRow" >
                                    <RowDefinition.Resources>
                                        <local:MultiplyConverter x:Key="multiplyConverter"/>
                                    </RowDefinition.Resources>
                                    <RowDefinition.Tag>
                                        <sys:Double>0.0</sys:Double>
                                    </RowDefinition.Tag>
                                    <RowDefinition.Height>
                                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                                            <Binding Path="DesiredSize.Height" ElementName="Content" />
                                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                                        </MultiBinding>
                                    </RowDefinition.Height>
                                </RowDefinition>
                            </Grid.RowDefinitions>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="MouseOver" />
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                  Storyboard.TargetProperty="(Panel.Background).
                        (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                                <EasingColorKeyFrame KeyTime="0"
                                           Value="{StaticResource DisabledControlDarkColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                  Storyboard.TargetProperty="(Border.BorderBrush).
                        (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                                <EasingColorKeyFrame KeyTime="0"
                                           Value="{StaticResource DisabledBorderLightColor}" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="Border" Grid.Row="0" BorderThickness="1" CornerRadius="2,2,0,0">
                                <Border.BorderBrush>
                                    <LinearGradientBrush EndPoint="0,1"
                                     StartPoint="0,0">
                                        <GradientStop Color="{DynamicResource BorderLightColor}"
                                Offset="0" />
                                        <GradientStop Color="{DynamicResource BorderDarkColor}"
                                Offset="1" />
                                    </LinearGradientBrush>
                                </Border.BorderBrush>
                                <Border.Background>
    
                                    <LinearGradientBrush StartPoint="0,0"
                                     EndPoint="0,1">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStopCollection>
                                                <GradientStop Color="{DynamicResource ControlLightColor}"
                                    Offset="0.0" />
                                                <GradientStop Color="{DynamicResource ControlMediumColor}"
                                    Offset="1.0" />
                                            </GradientStopCollection>
                                        </LinearGradientBrush.GradientStops>
                                    </LinearGradientBrush>
    
                                </Border.Background>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="20" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <ToggleButton OverridesDefaultStyle="True"
                              Template="{StaticResource ExpanderToggleButton}"
                              IsChecked="{Binding IsExpanded, Mode=TwoWay, 
                    RelativeSource={RelativeSource TemplatedParent}}">
                                        <ToggleButton.Background>
                                            <LinearGradientBrush EndPoint="0.5,1"
                                         StartPoint="0.5,0">
                                                <GradientStop Color="{DynamicResource ControlLightColor}"
                                    Offset="0" />
                                                <GradientStop Color="{DynamicResource ControlMediumColor}"
                                    Offset="1" />
                                            </LinearGradientBrush>
                                        </ToggleButton.Background>
                                    </ToggleButton>
                                    <ContentPresenter Grid.Column="1" Margin="4" ContentSource="Header" RecognizesAccessKey="True" />
                                </Grid>
                            </Border>
                            <Border x:Name="Content" Grid.Row="1"  BorderThickness="1,0,1,1" CornerRadius="0,0,2,2">
                                <Border.BorderBrush>
                                    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                                </Border.BorderBrush>
                                <Border.Background>
                                    <SolidColorBrush Color="{DynamicResource ContentAreaColorDark}" />
                                </Border.Background>
                                <ContentPresenter Margin="4" />
                            </Border>
    
                        </Grid>
                        <ControlTemplate.Triggers> 
                            <Trigger Property="IsExpanded" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="ContentRow" Storyboard.TargetProperty="Tag" From="0" To="1" Duration="0:0:1"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="ContentRow" Storyboard.TargetProperty="Tag" From="1" To="0" Duration="0:0:1"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
    
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <StackPanel>  
        <Expander  Header="Canny" >
            <StackPanel>
                <Button Content="A" />
                <Button Content="B" />
                <Button Content="C" />
            </StackPanel>
        </Expander>
    
        <Expander Header="Sobel" >
            <StackPanel>
                <Button Content="A" />
                <Button Content="B" />
                <Button Content="C" />
            </StackPanel>
        </Expander>
        <Expander Header="LoG" >
            <StackPanel>
                <Button Content="A" />
                <Button Content="B" />
                <Button Content="C" />
            </StackPanel>
        </Expander>
    
    </StackPanel>
    
    
    </Window>
    

    Which requires this converter:

    public class MultiplyConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return new GridLength((double)values[0] * (double)values[1], GridUnitType.Pixel);
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    The main point is to set DoubleAnimation on ContentRow.Height in the template. However, you need to use a MultiBinding to bind the To property of this animation.

    0 讨论(0)
提交回复
热议问题