【问题标题】:Frame.GoBack() succeeds on UI button click, fails on Windows software back button callbackFrame.GoBack() 在 UI 按钮单击时成功,在 Windows 软件后退按钮回调时失败
【发布时间】:2018-03-06 02:08:16
【问题描述】:

我有一个具有以下基本页面导航结构的语言学习应用:

  1. 开始 - 应用标题屏幕
  2. 语言 - 语言列表
  3. 课程 - 所选语言的课程列表
  4. 活动 - 包含所选课程的活动页面

前三页各有一个按钮导航到下一页,调用类似于:

private void ButtonClick(object sender, RoutedEventArgs e) => Frame.Navigate(typeof(SomePage));

在“活动”页面上,在用户通过按下按钮提交最后一个正确答案后,应用会像这样导航回来:

private async void SubmitAnswer_Click(object sender, RoutedEventArgs e)
{
    ...

    if (answerCorrect && allActivitiesComplete)
    {
        Frame.GoBack();
        return;
    }

    ...
}

有效;我返回到“课程”页面。如果我使用 IntelliSense 将鼠标悬停在 Frame 上,我会看到 BackStack 属性的计数为 3,之前的每一页都有一个。

但是,我还想显示软件后退按钮。为此,我有以下代码:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    ...
    var nav = SystemNavigationManager.GetForCurrentView();
    nav.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    ...
}

好的,现在按钮在桌面模式下显示在左上角。但是按下它什么也没做。所以我更新了以下内容:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    ...
    var nav = SystemNavigationManager.GetForCurrentView();
    nav.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    nav.BackRequested += (x, y) =>
    {
        Frame.GoBack();
    };
    ...
}

失败

Error HRESULT E_FAIL has been returned from a call to a COM component.

Frame.BackStack 显示0 的计数,而Frame.CanGoBackfalse。为什么这个代码流程和按钮按下代码流程不一致?

【问题讨论】:

  • 应用级别的后退按钮应该在 应用级别 注册,或者如果您的应用使用导航视图,那么在具有导航逻辑的页面(通常是 MainPage)中,这样导航堆栈和您所指的框架始终相同,以保持整个应用程序的一致性。此外,在实际调用 Frame.GoBack() 之前,最好检查一下 backstack 是否真的有任何页面 if(Frame.CanGoBack){ // go back }

标签: c# uwp navigation windows-10-universal


【解决方案1】:

理想情况下,您应该全局连接BackRequested 事件,而不是在特定页面的范围内。这是因为如果您添加一个事件处理程序OnNavigatedTo,您将在每次导航页面时添加另一个。这意味着单击后退按钮将多次导航。它还将将所有附加了处理程序的页面保留在内存中,这是一个严重的内存泄漏。至少你应该从使用 lamda 切换到事件处理方法,并在 OnNavigatedFrom 中取消订阅。

要正确实现应用标题栏后退按钮,您应该这样做:

  1. 观察FrameNavigated方法,根据CanGoBack属性适当显示/隐藏后退按钮
  2. BackRequested 处理程序中检查 CanGoBack 以确保可以导航

空白 UWP 应用的实现示例如下:

将以下方法添加到您的App.xaml.cs

private void SetupAppBarBackButton()
{
    _rootFrame.Navigated += RootFrame_Navigated;
    SystemNavigationManager.GetForCurrentView().BackRequested += App_BackRequested;
}

private void App_BackRequested(object sender, BackRequestedEventArgs e)
{
    if (_rootFrame.CanGoBack)
    {
        _rootFrame.GoBack();
    }
}

private void RootFrame_Navigated(object sender, NavigationEventArgs e)
{
    SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
        _rootFrame.CanGoBack
           ? AppViewBackButtonVisibility.Visible
           : AppViewBackButtonVisibility.Collapsed;
}

另外添加一个私有的_rootFrame 字段:

private Frame _rootFrame;

最后更新OnLaunched方法来存储根框架并设置后退按钮:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        ...

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;

        _rootFrame = rootFrame;
        SetupAppBarBackButton();
    }
    ...
}

请注意,如果您也在其他地方创建根框架(如其他激活路径),您需要存储框架并在那里调用SetupAppBarBackButton 方法。

【讨论】:

  • 是的,这就是问题所在。该错误会发生,因为事件处理程序将被创建多次,因此应用程序将导航回更多页面。当时的误解是页面的生命周期。我在 App.xaml.cs 中全局设置了一次后退按钮,它按预期工作。谢谢!
  • 很高兴它有帮助:-)!编码愉快!
【解决方案2】:

试试这个:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    ...

    Windows.UI.Core.SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += (s,a) =>
    {

        if (Frame.CanGoBack)
        {
            Frame.GoBack();
            a.Handled = true;
        }
    }
    ...
}

【讨论】:

  • 这帮助我在调试时发现了一些问题;谢谢。
  • 让我知道这是否有帮助以及您需要更多帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-11
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多