title: Xamarin Forms Navigation PopAsync isn't working
body: <p>I'm working on an app in Xamarin.Forms, and things have been going pretty steadily, until I ran into a navigation error. The thing that mystifies me about it is that I've already been successfully using the same code calls on other pages, but suddenly with this page, it isn't working. </p>
  
  <p>I have designed a bit of a unique navigation flow because of the visual result that I'm trying to accomplish, using a combination of master-detail that has two tiers of navigation pages using the normal push / pop code. I was following suggestions from <a href="https://medium.com/@yuka1984/master-detail-page-and-android-back-button-on-xamarin-forms-344bb0b8e873" rel="nofollow noreferrer">this article on medium.com</a>. </p>
  
  <p>The app initializes a main page called "Root Navigation" that initializes the master and detail pages.</p>
  
  <pre><code>public App()
  {
      InitializeComponent();
  
      MainPage = new RootNavigation();
  }
  </code></pre>
  
  <p>Root Navigation page:</p>
  
  <pre><code>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);
      }
  </code></pre>
  
  <p>To navigate forward in the app, I'm using a method called "set as detail page," that bridges the gap between master-detail behavior and navigation push / pop behavior. </p>
  
  <pre><code>private void SetAsDetailPage(ContentPage page)
  {
      NavigationPage.SetHasNavigationBar(newPage, false);
      if (newPage.GetType() == typeof(JobDetailPage))
      {
          newPage.ToolbarItems.Add(
              new ToolbarItem()
              {
                  Text = "Back",
                  Command = new Command(() =&gt; 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;
  }
  </code></pre>
  
  <p>Then, navigating backward calls one of two methods: "BackButton_Clicked()" or "ReturnToJobList()".</p>
  
  <pre><code>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();
  }
  </code></pre>
  
  <p>All of the pages that display read-only data have navigated without issue. When I'm done with the page, I have it raise a call to the MessagingCenter, and the root navigation receives the message and performs the desired navigation. For example, the "MenuPage_ItemSelected" event handler fires the code:</p>
  
  <pre><code>if (e.SelectedItem.ToString().ToLower() == "log out")
  {
      Device.InvokeOnMainThreadAsync(() =&gt;
      {
          InnerPage.PopToRootAsync();
          this.IsPresented = false;
      });
  }
  </code></pre>
  
  <p>This seems to be working fine, after I spent a while researching that when a secondary page calls 'pop to root' on a background thread, I have to invoke it on the main thread. </p>
  
  <p>Ok, so finally to the problem page: The "update job notes" page. The page raises a call to the Messaging Center, and the Root Navigation page picks that up and executes the following code:</p>
  
  <pre><code>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();
  }
  </code></pre>
  
  <p>Stepping through the code, it correctly executes <code>SaveNewJobNote()</code> and returns true. Then, it awaits displaying the alert "Saved Changes". Then, the code then gets stuck in an infinite while loop in the "ReturnToJobList()," forever printing out into the debug output <code>[0:] 'Application.Views.UpdateJobNotesPage' attempting Navigation.Pop()</code>. After about a million cycles I get tired of waiting and quit the debugger. I can't seem to do anything to make the page go away!</p>
  
  <p>I've tried a bunch of stuff with investigating the differences between <code>PopAsync</code> and <code>PopModalAsync</code>. After checking what's on the navigation stacks for the different pages in question, everything looks exactly like what I'd expect -- there's nothing on the modal stacks for anything (because I never called <code>PushModalAsync</code> on anything), there's 0 on the <code>RootNavigation</code> stack, 1 on the <code>OuterPage</code> stack, and 4 on the <code>InnerPage</code> stack. That all makes perfect sense to me, but it still doesn't pop the Update Job Notes page. I also tried code with <code>Navigation.RemovePage(page)</code> with no success. The only difference there was that the debugger included printing a warning about my code and suggesting I use <code>PopAsync()</code> instead. </p>
  
  <p>I also tried some different things with making the <code>PopAsync()</code> call from  <code>this.Navigation</code>, <code>this.Outer</code>, <code>this.Outer.Navigation</code>, <code>this.Inner</code>, <code>this.Inner.Navigation</code>, all with no success. </p>
  
  <p>I have already looked at a bunch of other questions on Stack Overflow including <a href="https://stackoverflow.com/questions/57743573">this question</a> and <a href="https://stackoverflow.com/questions/40397431">this question</a> but none of them seem to apply in this case. Any assistance would be greatly appreciated!!</p>