(新)解决方案 #2
另一种方法是对 NavigationPage、TabbedPage 类进行子类化,然后使用 Xamarin 提供的导航事件来跟踪当前页面。这些事件是:ModalPushed、ModalPopped、Pushed、Popped、CurrentPageChanged 等。
代码稍微多一点,但它在所有平台上的行为都更可预测,如果将应用置于后台,您无需保存任何额外的状态。
1) App.xaml.cs
public App()
{
...
this.ModalPushed += OnModalPushed;
this.ModalPopped += OnModalPopped;
}
//keep track of any modals presented
private readonly Stack<Page> ModalPages = new Stack<Page>();
void OnModalPushed(object sender, ModalPushedEventArgs e)
{
ModalPages.Push(e.Modal);
PageService.CurrentPage = FindCurrentPage();
}
void OnModalPopped(object sender, ModalPoppedEventArgs e)
{
ModalPages.Pop();
PageService.CurrentPage = FindCurrentPage();
}
public Page FindCurrentPage()
{
//If there is a Modal present, start there, or else start in the MainPage
Page root = ModalPages.Count > 0 ? ModalPages.Peek() : this.MainPage;
var tabbedPage = root as TabbedPage;
if (tabbedPage != null)
{
var currentTab = tabbedPage.CurrentPage;
var navPage = currentTab as NavigationPage;
if (navPage != null)
{
return navPage.CurrentPage;
}
else
{
return currentTab;
}
}
else
{
var navPage = root as NavigationPage;
if (navPage != null)
{
return navPage.CurrentPage;
}
return root;
}
}
2) CustomNavigationPage.cs
//All NavigationPage in your app should use this class!
public class CustomNavigationPage : NavigationPage
{
public BaseNavigationPage(Page page) : base(page)
{
this.Pushed += OnPushed;
this.Popped += OnPopped;
}
void OnPushed(object sender, NavigationEventArgs e)
{
PageService.CurrentPage = e.Page;
}
void OnPopped(object sender, NavigationEventArgs e)
{
PageService.CurrentPage = ((App)App.Current).FindCurrentPage();
}
}
3) CustomTabbedPage.cs --- 仅当您的应用使用标签时
public class CustomTabbedPage : TabbedPage
{
public CustomTabbedPage()
{
this.CurrentPageChanged += OnTabbedPageTabChanged;
}
void OnTabbedPageTabChanged(object sender, EventArgs e)
{
PageService.CurrentPage = ((App)App.Current).FindCurrentPage();
}
}
4) PageService.cs
public static class PageService
{
public Page CurrentPage
{
get;
set;
}
}
(原始)解决方案 #1
对我有用的是使用静态类来跟踪用户当前所在的页面。我的所有 ContentPages 都继承了一个 BasePage,它在 OnAppearing() 中设置当前页面。在 Android 中,您还必须处理应用暂停/恢复的特殊情况,因为 Xamarin 将在应用的根页面(不一定是视图中的页面)上调用 OnAppearing。
此方法允许我从我的视图模型层中的任何位置执行诸如推送/弹出页面之类的行为,而无需将视图模型直接耦合到视图。
PageService.cs:
public static class PageService
{
public Page CurrentPage
{
get;
set;
}
public Page SavedStatePage
{
get;
set;
}
}
BasePage.cs:
//Have all of your pages inherit this page
public abstract class BasePage : ContentPage
{
public BasePage () : base()
{
}
public override void OnAppearing()
{
protected override void OnAppearing()
{
base.OnAppearing();
//Mainly for Android, restore the current page to the last saved page when the app paused
if( PageService.SavedStatePage != null )
{
PageService.CurrentPage = PageService.SavedStatePage;
PageService.SavedStatePage = null;
}
else
{
//default behavior. Set the current page to the one currently appearing.
PageService.CurrentPage = this;
}
}
}
}
MainActivity.cs(在原生 Droid 项目中):
protected override void OnPause()
{
base.OnPause();
//save the current page before app pauses, because Xamarin doesn't always call OnAppearing on the correct page when resume happens
PageService.SavedStatePage = PageService.CurrentPage;
}