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
相关产品推荐
相关产品推荐

