我的问题并不像标题所暗示的那么简单。我知道我可以使用导航堆栈来查找最顶层的页面并调用该页面上的导航事件。
这就是我打算做的。
Page currentPage;
int index = Application.Current.MainPage.Navigation.NavigationStack.Count - 1;
currentPage = Application.Current.MainPage.Navigation.NavigationStack[index];
//after getting the correct page..
//await currentPage.Navigation.PushAsync(new SomePage());
我的问题是索引返回为-1
. 我相信由于我的页面层次结构/结构,增加了一些复杂性。
"我的应用"主页是一个LoginPage
- 一旦用户成功登录,他们就会被推送到模态页面,然后从那里进行其余的导航。
await Navigation.PushModalAsync(new NavigationPage(new MainMenu()));
当 NavigationStack 包含模式页面时,如何从不是从 ContentPage 继承的类中找到当前活动页面(用户正在查看的页面(?
我需要这样做,以便我的静态"帮助程序"类(特定于平台的iOS/Android代码访问(可以传递页面名称的字符串,并且此帮助程序类可以解析该名称,并导航到页面(如果存在(。在手机上发生事件后,正在通过特定于平台的实现访问帮助程序类(点击推送通知(
(新( 解决方案 #2
执行此操作的另一种方法是对导航页面、选项卡式页面类进行子类化,然后使用 Xamarin 提供给我们的导航事件来跟踪当前页面。 这些事件是:ModalPushed,ModalPopped,Pushed,Popped,CurrentPageChanged等。
这是更多的代码,但它在所有平台上的行为都是更可预测的,如果将应用程序置于后台,则无需保存任何其他状态。
1( 应用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( 自定义导航页面.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( 自定义选项卡式页面.cs仅当您的应用使用选项卡时才---
public class CustomTabbedPage : TabbedPage
{
public CustomTabbedPage()
{
this.CurrentPageChanged += OnTabbedPageTabChanged;
}
void OnTabbedPageTabChanged(object sender, EventArgs e)
{
PageService.CurrentPage = ((App)App.Current).FindCurrentPage();
}
}
4(页面服务.cs
public static class PageService
{
public Page CurrentPage
{
get;
set;
}
}
(原始(解决方案 #1
对我有用的是使用静态类来跟踪用户当前所在的页面。我让我所有的 ContentPages 都继承了一个 BasePage,它在 OnAppearing(( 中设置当前页面。在 Android 中,您还必须处理应用暂停/恢复的特殊情况,因为 Xamarin 将在应用程序的根页面(不一定是视图中的页面(上调用 OnAppear。
此方法允许我从视图模型层中的任何位置执行推送/弹出页面等行为,而无需将视图模型直接耦合到视图。
页面服务.cs:
public static class PageService
{
public Page CurrentPage
{
get;
set;
}
public Page SavedStatePage
{
get;
set;
}
}
基本页.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;
}
与其直接使用 PushModalSync 推送它,不如先实例化它并将其存储在应用程序中的静态变量中。这样,您始终可以从您喜欢的位置引用它。然后,您可以从那里确定哪个页面是当前页面或执行您需要执行的任何导航遍历。
Application.MyStaticVariable = new NavigationPage(new MainMenu());
await Navigation.PushModalAsync(Application.MyStaticVariable);