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

如何通过后台代码手动触发页面刷新动画?NavigationView切换Frame动画问题

嘿,这个场景我之前在做多模块导航应用的时候也踩过坑!你已经给每个Frame配置了导航栈内的页面切换动画,但切换激活Frame本身时没有过渡效果,其实可以通过几种方式手动触发,下面给你拆解几个实用的方案:

方案1:复用Frame内置的导航过渡动画

如果你给每个Frame配置的是系统内置的NavigationTransitionInfo(比如DrillInNavigationTransitionInfo、SlideNavigationTransitionInfo),那可以用一个“伪导航”的小技巧——让目标Frame重新导航到它当前显示的页面,同时指定过渡效果,这样就能直接复用你已经配置好的动画,还不会破坏页面的状态:

// 获取要切换到的目标Frame
var targetFrame = YourNavigationView.SelectedItem.Tag as Frame;
// 获取Frame当前显示的页面
var currentPage = targetFrame.Content as Page;

if (currentPage != null)
{
    // 导航回当前页面,传入你之前配置的过渡动画类型
    targetFrame.Navigate(
        currentPage.GetType(), 
        null, 
        new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight }
    );
}

注意:要确保你的Frame的CacheMode设置为Required或者Enabled,这样页面不会被重建,之前的操作状态就能完美保留。

方案2:用VisualStateManager自定义Frame切换动画

如果想要更灵活的动画效果(比如淡入淡出+平移组合),可以给每个Frame定义对应的激活/非激活视觉状态,然后在切换时手动触发状态切换:

首先在你的布局XAML里给Frame添加视觉状态和动画:

<Grid>
    <!-- 假设你的多个Frame都放在这个Grid里,默认只有激活的Frame可见 -->
    <Frame x:Name="HomeFrame" RenderTransformOrigin="0.5,0.5">
        <Frame.RenderTransform>
            <TranslateTransform X="0"/>
        </Frame.RenderTransform>
    </Frame>
    <Frame x:Name="SettingsFrame" Opacity="0" RenderTransformOrigin="0.5,0.5">
        <Frame.RenderTransform>
            <TranslateTransform X="20"/>
        </Frame.RenderTransform>
    </Frame>

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="FrameActivationStates">
            <!-- 主页Frame激活状态 -->
            <VisualState x:Name="HomeActive">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="HomeFrame" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="HomeFrame" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" To="0" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="SettingsFrame" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="SettingsFrame" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" To="20" Duration="0:0:0.3"/>
                </Storyboard>
            </VisualState>
            <!-- 设置页Frame激活状态 -->
            <VisualState x:Name="SettingsActive">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="SettingsFrame" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="SettingsFrame" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" To="0" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="HomeFrame" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="HomeFrame" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" To="-20" Duration="0:0:0.3"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

然后在后台切换Frame的代码里,触发对应的视觉状态:

private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
    var selectedItem = args.SelectedItem as NavigationViewItem;
    string targetState = selectedItem.Tag.ToString(); // 假设Tag存的是视觉状态名,比如"HomeActive"
    
    // 触发视觉状态切换,第三个参数true表示启用动画
    VisualStateManager.GoToState(this, targetState, true);
}

方案3:手动控制Storyboard播放

如果不想用VisualState,也可以直接创建Storyboard实例,在切换Frame的时候手动启动动画:

private void SwitchFrameWithAnimation(Frame oldFrame, Frame newFrame)
{
    // 创建退出动画:旧Frame淡出+向左平移
    var exitStoryboard = new Storyboard();
    var exitOpacityAnim = new DoubleAnimation { From = 1, To = 0, Duration = TimeSpan.FromMilliseconds(300) };
    var exitTranslateAnim = new DoubleAnimation { From = 0, To = -20, Duration = TimeSpan.FromMilliseconds(300) };
    Storyboard.SetTarget(exitOpacityAnim, oldFrame);
    Storyboard.SetTargetProperty(exitOpacityAnim, "Opacity");
    Storyboard.SetTarget(exitTranslateAnim, oldFrame);
    Storyboard.SetTargetProperty(exitTranslateAnim, "RenderTransform.(TranslateTransform.X)");
    exitStoryboard.Children.Add(exitOpacityAnim);
    exitStoryboard.Children.Add(exitTranslateAnim);

    // 创建进入动画:新Frame淡入+向右平移
    var enterStoryboard = new Storyboard();
    var enterOpacityAnim = new DoubleAnimation { From = 0, To = 1, Duration = TimeSpan.FromMilliseconds(300) };
    var enterTranslateAnim = new DoubleAnimation { From = 20, To = 0, Duration = TimeSpan.FromMilliseconds(300) };
    Storyboard.SetTarget(enterOpacityAnim, newFrame);
    Storyboard.SetTargetProperty(enterOpacityAnim, "Opacity");
    Storyboard.SetTarget(enterTranslateAnim, newFrame);
    Storyboard.SetTargetProperty(enterTranslateAnim, "RenderTransform.(TranslateTransform.X)");
    enterStoryboard.Children.Add(enterOpacityAnim);
    enterStoryboard.Children.Add(enterTranslateAnim);

    // 先播放退出动画,完成后播放进入动画
    exitStoryboard.Completed += (s, e) =>
    {
        oldFrame.Visibility = Visibility.Collapsed;
        newFrame.Visibility = Visibility.Visible;
        enterStoryboard.Begin();
    };

    exitStoryboard.Begin();
}

使用这个方法时,要确保每个Frame都添加了TranslateTransform作为RenderTransform,否则平移动画不会生效。

最后再提个小建议:切换Frame前最好先暂停旧Frame的导航栈动画,避免和切换动画冲突,等切换完成后再恢复,这样整体体验会更流畅。

内容的提问来源于stack exchange,提问作者Caleb Powell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:32:47