【问题标题】:Xamarin Forms Navigation PopAsync isn't workingXamarin 窗体导航 PopAsync 不起作用
【发布时间】:2020-01-06 19:44:29
【问题描述】:

我正在开发 Xamarin.Forms 中的一个应用程序,并且事情一直很稳定,直到我遇到导航错误。让我感到困惑的是,我已经成功地在其他页面上使用了相同的代码调用,但是突然在这个页面上,它不起作用。

我设计了一些独特的导航流程,因为我试图通过使用具有两层导航页面的主从结合使用普通推送/弹出代码来实现视觉效果。我正在遵循this article on medium.com 的建议。

应用程序初始化一个名为“Root Navigation”的主页,该主页初始化主页面和详细页面。

public App()
{
    InitializeComponent();

    MainPage = new RootNavigation();
}

根导航页面:

public partial class RootNavigation : MasterDetailPage
{
    private MenuPage menuPage;
    private NavigationPage OuterPage;
    private NavigationPage InnerPage;

    public RootNavigation()
    {
        this.Master = this.menuPage = new MenuPage();
        this.menuPage.MenuItemsListView.ItemSelected += Menu_ItemSelected;

        var viewModel = new SelectEmployeeViewModel();
        var page = new SelectEmployeePage(viewModel);
        SetAsDetailPage(page);
    }

为了在应用程序中向前导航,我使用了一种称为“设置为详细信息页面”的方法,它弥合了主从行为和导航推送/弹出行为之间的差距。

private void SetAsDetailPage(ContentPage page)
{
    NavigationPage.SetHasNavigationBar(newPage, false);
    if (newPage.GetType() == typeof(JobDetailPage))
    {
        newPage.ToolbarItems.Add(
            new ToolbarItem()
            {
                Text = "Back",
                Command = new Command(() => BackButton_Clicked())
            });
    }
    this.InnerPage = this.InnerPage ?? new NavigationPage();
    this.InnerPage.Navigation.PushAsync(page);
    this.OuterPage = this.OuterPage ?? new NavigationPage(this.InnerPage);
    this.Detail = this.Detail ?? this.OuterPage;
}

然后,向后导航调用以下两种方法之一:“BackButton_Clicked()”或“ReturnToJobList()”。

private void ReturnToJobList()
{
    while (InnerPage.CurrentPage.GetType() != typeof(JobsPage))
    {
        var current = InnerPage.CurrentPage.ToString();
        System.Diagnostics.Debug.WriteLine($"'{current}' attempting Navigation.Pop()");
        InnerPage.PopAsync();
    }
}

private void BackButton_Clicked()
{
    this.InnerPage.PopAsync();
}

所有显示只读数据的页面都已顺利导航。完成页面后,我让它调用 MessagingCenter,根导航接收消息并执行所需的导航。例如,“MenuPage_ItemSelected”事件处理程序触发代码:

if (e.SelectedItem.ToString().ToLower() == "log out")
{
    Device.InvokeOnMainThreadAsync(() =>
    {
        InnerPage.PopToRootAsync();
        this.IsPresented = false;
    });
}

这似乎工作正常,在我花了一段时间研究后,当辅助页面在后台线程上调用“pop to root”时,我必须在主线程上调用它。

好的,终于到了问题页面:“更新工作说明”页面。该页面引发了对消息中心的调用,根导航页面选择该调用并执行以下代码:

private async void SaveJobNotes(ContentPage sender)
{
    if (sender is UpdateJobNotesPage notesPage)
    {
        bool result = await SaveNewJobNote(notesPage);
        var message = result ? "Saved changes" : "An error occurred; changes not saved";
        await DisplayAlert("Save", message, "OK");
    }

    ReturnToJobList();
}

单步执行代码,它正确执行SaveNewJobNote() 并返回true。然后,它等待显示警报“已保存的更改”。然后,代码在“ReturnToJobList()”中陷入无限循环,永远打印到调试输出[0:] 'Application.Views.UpdateJobNotesPage' attempting Navigation.Pop()。大约一百万个周期后,我厌倦了等待并退出调试器。我似乎无法让页面消失!

我尝试了很多方法来调查PopAsyncPopModalAsync 之间的差异。在检查了相关不同页面的导航堆栈上的内容后,一切看起来都与我期望的完全一样——模式堆栈上没有任何内容(因为我从未在任何内容上调用过PushModalAsync),@ 上有 0 987654335@ 堆栈,OuterPage 堆栈上的 1 个,InnerPage 堆栈上的 4 个。这一切对我来说都很有意义,但它仍然没有弹出更新工作说明页面。我还尝试了Navigation.RemovePage(page) 的代码,但没有成功。唯一的区别是调试器包括打印关于我的代码的警告并建议我改用PopAsync()

我还尝试了一些不同的方法,从this.Navigationthis.Outerthis.Outer.Navigationthis.Innerthis.Inner.Navigation 拨打PopAsync(),均未成功。

我已经查看了有关 Stack Overflow 的许多其他问题,包括 this questionthis question,但它们似乎都不适用于这种情况。任何帮助将不胜感激!

【问题讨论】:

  • ,根据你的描述,我这边无法复现你的问题,能否提供一个简单的可以在github上复现你的问题,我会下载你的样例进行测试,请指点有这个问题。
  • 我想知道的是这一行this.InnerPage = this.InnerPage ?? new NavigationPage();,可能是在您的场景中,InnerPage 未设置为 NavigationPage()?

标签: c# xamarin.forms navigation


【解决方案1】:

我记得这件事发生在我身上。 我忘记了到底是什么原因,但我也有一些时髦的导航。我的问题是围绕弹出窗口,有一次,他们正在创建一个新堆栈。所以当我弹出时,我得到了意想不到的结果。

我怀疑您还在某处创建另一个堆栈,尤其是当您在调试器中处于 0 时。

罪魁祸首很可能潜伏在 InvokeOnMainThread() 周围。

【讨论】:

  • 澄清一下,我没有遇到包含InvokeOnMainThread 的代码块的任何问题。我遇到了应该调用InnerPage.PopAsync() 的代码块问题,直到作业列表页面成为堆栈的顶部页面。
  • 我明白了。我的意思更多的是你在主线程上调用可能会改变堆栈。在某个地方创建了一个额外的堆栈,这就是为什么您弹出该堆栈而看不到其他页面的原因。
【解决方案2】:

在作业列表页面可见之前,我还没有真正弄清楚我创建的应该调用InnerNavigation.PopAsync() 的代码块有什么问题。似乎该代码块中的所有变量都评估为我期望的值,但不知何故,它似​​乎无法从堆栈中弹出任何内容。

但是,我确实更改了处理保存作业注释的代码块,它现在确实将保存作业注释页面从堆栈中弹出。

private async void SaveJobNotes(ContentPage sender)
{
    this.InnerPage.PopAsync(); //I don't understand why this works and the 
                                //other didn't, but it correctly pops the page

    if (sender is UpdateJobNotesPage notesPage)
    {
        bool noteSaved = await SaveNewJobNote(notesPage);
        bool progressSaved = await SaveJobProgress(notesPage);
        var message = noteSaved && progressSaved ? 
            "Changes were save successfully" : 
            "An error occurred; changes not saved";
        await DisplayAlert("Save", message, "OK");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多