You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免WPF Expander控件加载时自动播放展开动画?

问题:Expander默认展开时加载阶段自动播放动画的解决

假设有一个WPF控件,其Trigger的EnterAction/ExitActions中包含Storyboard。本文场景为基于IsExpanded属性实现展开/收起动画的Expander控件,点击时动画运行正常,但当默认设置IsExpanded="True"时,控件加载阶段会自动播放展开动画,这是需要解决的问题。


最初的思路是使用VisualState并扩展Expander控件,以避免加载时运行动画,代码如下:

public class MyExpander : Expander
{
    static MyExpander()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyExpander), new FrameworkPropertyMetadata(typeof(MyExpander)));
    }

    public override void OnApplyTemplate()
    {
        VisualStateManager.GoToState(this, IsExpanded ? "Expanded" : "Collapsed", false);

        base.OnApplyTemplate();
    }

    protected override void OnExpanded()
    {
        VisualStateManager.GoToState(this, "Expanded", IsLoaded && IsVisible);

        System.Diagnostics.Debug.WriteLine($"Expand? {IsLoaded} && {IsVisible}, {IsInitialized}");

        base.OnExpanded();
    }

    protected override void OnCollapsed()
    {
        VisualStateManager.GoToState(this, "Collapsed", IsLoaded && IsVisible);

        base.OnCollapsed();
    }
}

同时在第一个FrameworkElement(本文中为Border)的子级ControlTemplate中添加如下内容:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="ExpansionStates">
        <VisualStateGroup.Transitions>
            <VisualTransition From="Collapsed" To="Expanded">
                <!--<VisualTransition.GeneratedEasingFunction>
                    <CircleEase EasingMode="EaseInOut"/>
                </VisualTransition.GeneratedEasingFunction>-->
            </VisualTransition>

            <VisualTransition From="Expanded" To="Collapsed">
                <!--<VisualTransition.GeneratedEasingFunction>
                    <CircleEase EasingMode="EaseInOut"/>
                </VisualTransition.GeneratedEasingFunction>-->
            </VisualTransition>
        </VisualStateGroup.Transitions>

        <VisualState x:Name="Expanded">
            <Storyboard x:Name="ExpandStoryboard">
                <DoubleAnimation Storyboard.TargetName="PresenterScaleTransform" Storyboard.TargetProperty="ScaleY" Duration="0:0:0.2" To="1" BeginTime="0:0:0">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <DoubleAnimation Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="Opacity" Duration="0:0:0.05" To="1" BeginTime="0:0:0.15">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <DoubleAnimation Storyboard.TargetName="SymbolRotateTransform" Storyboard.TargetProperty="Angle" Duration="0:0:0.2" To="180" BeginTime="0:0:0.1">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <ObjectAnimationUsingKeyFrames BeginTime="0:00:00" Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" KeyTime="0:0:0"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>

        <VisualState x:Name="Collapsed">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="PresenterScaleTransform" Storyboard.TargetProperty="ScaleY" Duration="0:0:0.2" To="0" BeginTime="0:0:0">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <DoubleAnimation Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="Opacity" Duration="0:0:0.1" To="0" BeginTime="0:0:0">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <DoubleAnimation Storyboard.TargetName="SymbolRotateTransform" Storyboard.TargetProperty="Angle" Duration="0:0:0.2" To="0" BeginTime="0:0:0.1">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseIn"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>

                <ObjectAnimationUsingKeyFrames BeginTime="0:00:00" Storyboard.TargetName="ExpandSite" Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" KeyTime="0:0:0.2"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

尝试调整VisualTransition的配置,但效果反而变差。当前配置下点击时动画运行正常,但仍无法阻止加载阶段的动画播放。


内容的提问来源于stack exchange,提问作者Nicke Manarin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:02:04