如何在WPF中为控件实现收缩动画

如何在WPF中为控件实现收缩动画,wpf,xaml,animation,Wpf,Xaml,Animation,我想要一个控件(例如GroupBox),当它变为可见时显示一个生长动画,当可见性变为“折叠”时显示一个收缩动画 因此,我创建了一个样式,它实现了动画的增长和收缩效果,如下面一个小示例应用程序中所示(如下所示) 但是,仅显示成长动画。groupbox将立即消失,而不是显示收缩动画 谁能告诉我,为什么? 更好的是,如何修复它 <Window x:Class="ShrinkTest.MainWindow" xmlns="http://schemas.microsoft.com/w

我想要一个控件(例如GroupBox),当它变为可见时显示一个生长动画,当可见性变为“折叠”时显示一个收缩动画

因此,我创建了一个样式,它实现了动画的增长和收缩效果,如下面一个小示例应用程序中所示(如下所示)

但是,仅显示成长动画。groupbox将立即消失,而不是显示收缩动画

谁能告诉我,为什么? 更好的是,如何修复它

<Window x:Class="ShrinkTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="FrameworkElement" x:Key="ExpandableElement">
            <Setter Property="RenderTransformOrigin" Value="0.5 0" />
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <ScaleTransform/>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Visibility" Value="Visible">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="1" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                </Trigger>
                <Trigger Property="Visibility" Value="Hidden">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1" To="0" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Margin="8" Width="140" Click="ButtonBase_OnClick">Expand / Shrink</Button>

        <TextBlock Grid.Row="1" Text="--- Header ---"/>

        <GroupBox x:Name="GroupBox" Grid.Row="2" Header="GroupBox" Style="{StaticResource ExpandableElement}" >
            <StackPanel Orientation="Vertical">
                <TextBlock Text="Test Test Test"/>
                <TextBlock Text="Test Test Test"/>
                <TextBlock Text="Test Test Test"/>
                <TextBlock Text="Test Test Test"/>
                <TextBlock Text="Test Test Test"/>
            </StackPanel>
        </GroupBox>

        <TextBlock Grid.Row="3" Text="--- Footer ---"/>
    </Grid>
</Window>

展开/收缩

我也有类似的问题。想想看。。。您的问题是,当动画可见时,您可以看到它,但当它隐藏时,您无法看到它。这也是你为什么。。。因为它是隐藏的。我知道,这是一个相当不令人满意的答案,但事实就是这样

至于如何修复它。。。说起来很简单,但实现起来却不简单。简单地说,您必须运行动画直到结束,然后将
可见性设置为
隐藏。因此,不幸的是,这意味着在
触发器
中设置
可见性
属性的简单方法不再可行。。。让它可见是可以的,但不是为了隐藏

在我的例子中,我有一个完整的框架,我把我的动画构建到其中。但基本上说,当我从集合中移除项目时,项目在内部并没有被实际移除,而是启动了其退出动画。只有动画完成后,内部集合才会实际删除该项


因此,如果您可能会感到麻烦,那么您必须实现这样的功能,即不将
可见性
属性设置为
隐藏
,而是将另一个属性设置为
,从而触发动画,并在调用该动画中的
完成
事件时,然后将
可见性
属性设置为
隐藏

Sheridan是正确的。一旦控件变为不可见,应用哪个动画就无关紧要了。:-)

因此,我创建了一个特殊的ExpandingContentControl:

public class ExpandingContentControl : ContentControl
{
    public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
        "IsExpanded", typeof(bool), typeof(ExpandingContentControl), new PropertyMetadata(false));

    public bool IsExpanded
    {
        get { return (bool)GetValue(IsExpandedProperty); }
        set { SetValue(IsExpandedProperty, value); }
    }

    public ExpandingContentControl()
    {
        Visibility = IsExpanded ? Visibility.Visible : Visibility.Collapsed;
    }
}
但是样式也有一个问题:创建两个绑定到同一属性的不同值的触发器显然不起作用。 相反,我现在只使用一个触发器,其中EnterAction实现增长,ExitAction实现收缩控件:

<Style TargetType="controls:ExpandingContentControl" >
    <Setter Property="RenderTransformOrigin" Value="0.5 1" />
    <Setter Property="RenderTransform">
        <Setter.Value>
            <ScaleTransform/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsExpanded" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" >
                            <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" KeyTime="00:00:00"/>
                        </ObjectAnimationUsingKeyFrames>
                        <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="1" 
                                         Duration="0:0:0.3" DecelerationRatio="0.4"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1" To="0" Duration="0:0:0.2" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="00:00:0.2"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style> 


它是否会是
折叠的
而不是
隐藏的
,并且对象的可见性已经设置为默认值?或者您是否尝试过放弃
隐藏
的第二个触发器,只需将第二个动画输入到
可见
的一个触发器,除了作为
退出
而不是
进入
?如果不进行测试,这将是我的第一个想法。隐藏触发器是在可见性更改为隐藏后执行的,因此,要么在控件隐藏时播放情节提要,要么WPF足够聪明,知道它未显示且不播放情节提要。