【问题标题】:Xamarin Forms - Find current page of App from class not inhereting from ContentPageXamarin Forms - 从类中查找应用程序的当前页面,而不是从 ContentPage 继承
【发布时间】:2017-08-24 01:05:24
【问题描述】:

我的问题并不像标题所暗示的那么简单。我知道我可以使用导航堆栈找出最顶层的页面并在该页面上调用导航事件。

这就是我打算做的事情..

        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 代码访问的)传递页面名称的字符串,并且该帮助程序类可以解析该名称,并导航到页面(如果存在)。在手机上发生事件(点击推送通知)后,通过特定于平台的实现访问帮助程序类

【问题讨论】:

    标签: c# static xamarin.forms navigation modal-dialog


    【解决方案1】:

    (新)解决方案 #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;
    } 
    

    【讨论】:

    • 这与我最终实施的非常接近 - 感谢您抽出宝贵时间回复!
    • 我在这个答案的顶部添加了一个新的解决方案#2,我觉得这是一种比依赖 OnAppearing() 方法更好的处理方式。我发现 OnAppearing 的问题在于它在 UWP 上的行为与在 iOS/Droid 上的行为不同。
    【解决方案2】:

    与其直接使用 PushModalSync 推送它,不如先实例化它并将其存储在 Application 中的静态变量中。这样你就可以随时从你喜欢的地方引用它。然后,您可以从那里确定哪个页面是当前页面或执行您需要执行的任何导航遍历。

    Application.MyStaticVariable = new NavigationPage(new MainMenu());
    await Navigation.PushModalAsync(Application.MyStaticVariable);
    

    【讨论】:

      猜你喜欢
      • 2015-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 2023-03-31
      • 1970-01-01
      相关资源
      最近更新 更多