C# Frame.GoBack()在UI按钮单击时成功,在Windows软件返回按钮回调时失败
我有一个具有以下基本页面导航结构的语言学习应用程序: 开始-应用程序标题屏幕 语言-语言列表 课程-所选语言的课程列表 活动-包含所选课程的活动的页面 前三个页面各有一个按钮,可通过类似以下的调用导航到下一个页面:C# Frame.GoBack()在UI按钮单击时成功,在Windows软件返回按钮回调时失败,c#,uwp,navigation,windows-10-universal,C#,Uwp,Navigation,Windows 10 Universal,我有一个具有以下基本页面导航结构的语言学习应用程序: 开始-应用程序标题屏幕 语言-语言列表 课程-所选语言的课程列表 活动-包含所选课程的活动的页面 前三个页面各有一个按钮,可通过类似以下的调用导航到下一个页面: private void ButtonClick(object sender, RoutedEventArgs e) => Frame.Navigate(typeof(SomePage)); 在“活动”页面上,当用户按下按钮提交最后一个正确答案后,应用程序将按如下方式返回:
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将鼠标悬停在帧上,我会看到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();
};
...
}
这在以下情况下失败:
Frame.backbackback显示计数为0,Frame.CanGoBack为false。为什么此代码流与按钮按下代码流不一致?请尝试以下操作:
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;
}
}
...
}
理想情况下,您应该全局连接BackRequested事件,而不是在特定页面的范围内。这是因为如果在OnNavigatedTo上添加事件处理程序,则每次导航页面时都会添加另一个事件处理程序。这意味着单击“后退”按钮将向后导航几次。此外,它还会将附加处理程序的所有页面保留在内存中,这是一种严重的内存泄漏。至少您应该从使用lamda切换到事件处理程序方法,并在OnNavigatedFrom中取消订阅它 要正确实施应用程序标题栏后退按钮,应执行以下操作: 观察框架导航方法,根据CanGoBack属性适当显示/隐藏后退按钮 在BackRequested处理程序中,检查CanGoBack以确保导航是可能的 空白UWP应用程序的实现示例如下: 将以下方法添加到App.xaml.cs: 还添加一个私有的根框架字段: 最后更新OnLaunched方法以存储根帧并设置back按钮:
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方法。应用程序级别的后退按钮应在应用程序级别注册,或者如果您的应用程序使用导航视图,则在具有导航逻辑的页面中,通常在主页上注册,因此,为了在整个应用程序中保持一致性,导航堆栈和您所指的框架始终相同。另外,在实际调用Frame.GoBack之前,最好检查backbackback在Frame.CanGoBack{//go back}中是否有页面。是的,这就是问题所在。发生此错误的原因是事件处理程序将被创建多次,因此应用程序将导航回超过可能的页面。当时的误解是页面的生命周期。我在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;
}
private Frame _rootFrame;
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();
}
...
}