C# UWP连接的动画在第二次使用后崩溃

C# UWP连接的动画在第二次使用后崩溃,c#,animation,uwp,uwp-xaml,argumentexception,C#,Animation,Uwp,Uwp Xaml,Argumentexception,我用一个单击事件连接了两个窗体,该事件在两个方向上触发一个连接的动画。第一次前进和后退时,效果很好。第二次转发时,它工作,但第二次尝试返回时,会导致应用程序崩溃,但出现以下异常: System.ArgumentException:参数不正确。无法启动动画-源元素不在元素树中 这发生在SecondPage_BackRequested的第一行,但仅在第二次执行时发生。第一次执行可以完美地工作并设置动画 任何帮助都将不胜感激。我已经浏览了相关的动画文档,据我所知,这是应该如何使用它的,但是我找不到任何

我用一个单击事件连接了两个窗体,该事件在两个方向上触发一个连接的动画。第一次前进和后退时,效果很好。第二次转发时,它工作,但第二次尝试返回时,会导致应用程序崩溃,但出现以下异常:

System.ArgumentException:参数不正确。无法启动动画-源元素不在元素树中

这发生在SecondPage_BackRequested的第一行,但仅在第二次执行时发生。第一次执行可以完美地工作并设置动画

任何帮助都将不胜感激。我已经浏览了相关的动画文档,据我所知,这是应该如何使用它的,但是我找不到任何地方出现的这个错误的参考

我的代码(MainPageViewModel因不相关而省略,但可根据请求添加):

MainPage.xaml

<Page
    x:Class="AnimTest.Views.Main.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:models="using:AnimTest.Models"
    xmlns:main="using:AnimTest.Views.Main"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          Padding="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0"
                   Style="{ThemeResource HeaderTextBlockStyle}"
                   Text="AnimTest"/>
        <GridView x:Name="TileGrid"
                  Grid.Row="1"
                  IsItemClickEnabled="True"
                  ItemsSource="{x:Bind ViewModel.Tiles, Mode=OneWay}"
                  ItemClick="GridView_ItemClick"
                  Loaded="TileGrid_Loaded">
            <GridView.ItemTemplate>
                <DataTemplate x:DataType="models:Tile">
                    <Border x:Name="TileBorder"
                            Background="Red"
                            MinHeight="150"
                            MinWidth="200">
                        <StackPanel Orientation="Vertical"
                                    VerticalAlignment="Center">
                            <SymbolIcon Symbol="World"/>
                            <TextBlock Text="{x:Bind Name}"
                                       HorizontalTextAlignment="Center"/>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </GridView.ItemTemplate>
        </GridView>
    </Grid>
</Page>
SecondPage.xaml

<Page
    x:Class="HomeTiles.Views.Thermostat.ThermostatPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HomeTiles.Views.Thermostat"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Border x:Name="MainBorder"
            Background="Red">
    </Border>
</Page>

问题实际上不在于连接的动画,而在于导航事件

第一次到达
SecondPage
时,您连接了
backrequest
事件,当您返回时,一切正常。但是,即使在从
第二页导航后,事件处理程序仍保持与事件的连接。这是一个问题,因为一旦再次导航到
SecondPage
,现在偶数将注册两次。处理程序第一次运行时也会失败,因为第一个处理程序连接到页面的前一个实例,并且连接的动画已经完成了。最后-由于该事件,该页将永远留在内存中,这可能导致严重的内存泄漏

解决方案非常简单-您必须确保在离开页面时不会忘记取消订阅偶数处理程序,例如在
OnNavigatedFrom
方法中,并在
OnNavigatedTo
方法中订阅,以提高清晰度:

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

    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
        SystemNavigationManager.GetForCurrentView().BackRequested -= SecondPage_BackRequested;
    }

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

    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);
    }
}
为了避免这种问题,我通常在
App
中为整个应用程序设置
backrequest
事件,并在启动时只订阅一次。然后,您可以将连接的动画代码放入
OnNavigatedFrom
方法中,而不必订阅
backrequest

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);       
    ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("borderOut", MainBorder);
}

问题实际上不在于连接的动画,而在于导航事件

第一次到达
SecondPage
时,您连接了
backrequest
事件,当您返回时,一切正常。但是,即使在从
第二页导航后,事件处理程序仍保持与事件的连接。这是一个问题,因为一旦再次导航到
SecondPage
,现在偶数将注册两次。处理程序第一次运行时也会失败,因为第一个处理程序连接到页面的前一个实例,并且连接的动画已经完成了。最后-由于该事件,该页将永远留在内存中,这可能导致严重的内存泄漏

解决方案非常简单-您必须确保在离开页面时不会忘记取消订阅偶数处理程序,例如在
OnNavigatedFrom
方法中,并在
OnNavigatedTo
方法中订阅,以提高清晰度:

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

    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
        SystemNavigationManager.GetForCurrentView().BackRequested -= SecondPage_BackRequested;
    }

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

    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);
    }
}
为了避免这种问题,我通常在
App
中为整个应用程序设置
backrequest
事件,并在启动时只订阅一次。然后,您可以将连接的动画代码放入
OnNavigatedFrom
方法中,而不必订阅
backrequest

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);       
    ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("borderOut", MainBorder);
}

就是这样!我没有注意到事件发生在SystemNavigationManager上,而不是页面本身,因此处理程序在处理页面时不会自动清除。非常感谢。就是这样!我没有注意到事件发生在SystemNavigationManager上,而不是页面本身,因此处理程序在处理页面时不会自动清除。非常感谢。