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

UWP Connected Animation二次返回时崩溃问题求助

我遇到过完全相同的问题,这个崩溃的核心原因是你在SecondPage的构造函数里重复绑定了BackRequested事件,却没有在页面离开时解绑它。

每次你导航到SecondPage时,都会创建一个新的页面实例(默认Frame不缓存页面),而每个实例都会在构造函数里给SystemNavigationManager.GetForCurrentView().BackRequested添加一个事件处理程序。当你第二次触发返回操作时,多个绑定的处理程序会依次执行:第一个处理程序调用Frame.GoBack()后,当前的SecondPage实例已经被从元素树中卸载,MainBorder不再属于活跃的元素树;但第二个处理程序还会尝试执行PrepareToAnimate,这就触发了"The parameter is incorrect. Cannot start animation - the source element is not in the element tree."异常。

解决方案1:正确绑定/解绑BackRequested事件

把事件注册从构造函数移到OnNavigatedTo,并在OnNavigatedFrom中解绑,这样每个页面实例只会在活跃时绑定事件:

public sealed partial class SecondPage : Page
{
    public SecondPage()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        // 仅在页面进入视野时显示返回按钮并绑定事件
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
        SystemNavigationManager.GetForCurrentView().BackRequested += SecondPage_BackRequested;

        // 启动进入动画
        var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("borderIn");
        animation?.TryStart(MainBorder);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
        // 页面离开时解绑事件并隐藏返回按钮
        SystemNavigationManager.GetForCurrentView().BackRequested -= SecondPage_BackRequested;
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
    }

    private void SecondPage_BackRequested(object sender, BackRequestedEventArgs e)
    {
        if (Frame?.CanGoBack == true)
        {
            ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("borderOut", MainBorder);
            Frame.GoBack();
            e.Handled = true;
        }
    }
}

解决方案2:修复MainPage的返回动画目标(可选但推荐)

你当前的MainPage在返回时固定使用ViewModel.Tiles[0]作为动画目标,这会导致如果点击的不是第一个Tile,返回动画会错位。我们可以记录选中的Tile,确保返回时对应正确的元素:

public sealed partial class MainPage : Page
{
    public MainPageViewModel ViewModel => (MainPageViewModel)DataContext;
    private Tile _selectedTile; // 记录选中的Tile

    public MainPage()
    {
        InitializeComponent();
        DataContext = new MainPageViewModel();
    }

    private void GridView_ItemClick(object sender, ItemClickEventArgs e)
    {
        _selectedTile = e.ClickedItem as Tile;
        TileGrid.PrepareConnectedAnimation("borderIn", _selectedTile, "TileBorder");
        Frame.Navigate(typeof(SecondPage));
    }

    private async void TileGrid_Loaded(object sender, RoutedEventArgs e)
    {
        var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("borderOut");
        if (animation != null && _selectedTile != null)
        {
            var success = await TileGrid.TryStartConnectedAnimationAsync(animation, _selectedTile, "TileBorder");
            _selectedTile = null; // 动画完成后清空,避免下次加载错误
        }
    }
}

这两个修改结合起来,既能解决重复事件触发导致的崩溃,也能让返回动画更准确。

内容的提问来源于stack exchange,提问作者Shaun Hamman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:02:08