问题
tl;dr
I have 3 Pages MainPage.xaml
, BlankPage1.xaml
, BlankPage2.xaml
with Button
on MainPage
and BlankPage1
that navigates to BlankPage1
and BlankPage2
Respectively. I enabled System Back Button so that i can go back to previous page.
Button
Tap on MainPage
navigates to BlankPage1
and Button
Tap on BlankPage1
navigates to BlankPage2
. This works fine.
Problem: When I tap Back Button
on BlankPage2
it goes back to BlankPage
. Now when I tap the Button
on BlankPage1
it goes to BlankPage2
but when i Tap the Back Button
, instead of going to BlankPage1
it navigates directly to MainPage
.
Below is my code.
MainPage.xaml
<Page
x:Class="App2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Content="GoTo Page 1" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Button_Tapped"/>
</Grid>
</Page>
MainPage.xaml.cs
using Windows.UI.Xaml.Controls;
namespace App2
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Button_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
Frame.Navigate(typeof(BlankPage1));
}
}
}
BlankPage1.xaml
<Page
x:Class="App2.BlankPage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Content="GoTo Page 2" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Button_Tapped"/>
</Grid>
</Page>
BlankPage1.xaml.cs
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace App2
{
public sealed partial class BlankPage1 : Page
{
public BlankPage1()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (Frame.CanGoBack)
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += (s, a) =>
{
if (Frame.Content.GetType() == typeof(BlankPage1))
{
if (Frame.CanGoBack)
{
Frame.GoBack();
a.Handled = true;
}
}
};
}
else
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}
}
private void Button_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
Frame.Navigate(typeof(BlankPage2));
}
}
}
BlankPage2.xaml
<Page
x:Class="App2.BlankPage2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Text="Final Page" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Page>
BlankPage2.xaml.cs
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace App2
{
public sealed partial class BlankPage2 : Page
{
public BlankPage2()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (Frame.CanGoBack)
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += (s, a) =>
{
if (Frame.Content.GetType() == typeof(BlankPage2))
{
if (Frame.CanGoBack)
{
Frame.GoBack();
a.Handled = true;
}
}
};
}
else
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}
}
}
}
回答1:
Every time you navigate to a page, the OnNavigatedTo
method is being called and you're registering a new handler for the BackRequested
event, meaning it'll execute multiple times when you press the back button. You should unsubscribe to that event in your OnNavigatedFrom
method of each page.
Setting Handled = true
doesn't mean that other subscriptions for that event won't be executed, it just means:
If you don't mark the event as handled, the system decides whether to navigate away from the app (on the Mobile device family) or ignore the event (on the Desktop device family).
回答2:
Building up on the answer from @Decade Moon, I would suggest you could even centralize the logic into the App
class for easier manageability and cleaner Page
code-behinds.
Add the following line to App.OnLaunched
method:
SystemNavigationManager.GetForCurrentView().BackRequested += App_BackRequested;
And implement the handler like this:
private void App_BackRequested(object sender, BackRequestedEventArgs e)
{
var frame = ( Frame )Window.Current.Content;
if ( frame.CanGoBack )
{
frame.GoBack();
e.Handled = true;
}
}
We grab the frame of the current window and check if we can navigate back. In case it is possible, we handle the event and navigate. The advantage of this is, that you can now remove all BackRequested
related actions on all pages.
You can also do similar thing for the AppViewBackButtonVisibility
: add the following to the end of OnLaunched
:
rootFrame.Navigated += RootFrame_Navigated;
And now implement the handler as:
private void RootFrame_Navigated(object sender, NavigationEventArgs e)
{
var frame = (Frame)Window.Current.Content;
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
frame.CanGoBack ? AppViewBackButtonVisibility.Visible :
AppViewBackButtonVisibility.Collapsed;
}
Each time the frame navigates, the visibility of the back button will automatically update.
来源:https://stackoverflow.com/questions/40954200/navigation-issue-in-uwp