question

PatrickRyder avatar image
0 Votes"
PatrickRyder asked PatrickRyder commented

Why can't I access CurrentPage in the Xamarin.Forms.Shell Navigated event?

I am unable to access the value of CurrentPage in the Navigated event of the Xamarin.Forms.Shell.

I have created my own subclass of Shell that contains a top-level tab with two views and then a third screen that is
intended to be accessed modally from either of the two top-level screens. The set-up code is something like this:

 public partial class MyNavigation : Shell
 {
     public MyNavigation()
     {
         Items.Add( new TabBar()
         {
             Items =
             {
                 new ShellContent
                 {
                     Icon = ImageSource.FromResource( _HomeIcon ),
                     ContentTemplate = new DataTemplate( typeof( HomeView ) ),
                     Route = "Home",
                 },
                 new ShellContent
                 {
                     Icon = ImageSource.FromResource( _SettingsIcon ),
                     ContentTemplate = new DataTemplate( typeof( SettingsView ) ),
                     Route = "Settings",
                 }
             }
         });
    
         Routing.RegisterRoute( "ModalView", typeof( ModalView ) );
    
         Navigating += MyNavigation_Navigating;
         Navigated += MyNavigation_Navigated;
     }
    
     public async Task NavigateAsync( string screenName ) => await GoToAsync( screenName );
    
     private void MyNavigation_Navigating( object sender, ShellNavigatingEventArgs e )
     {
         // This is okay.
         ContentPage viewBase = (ContentPage)CurrentPage;
     }
    
     private void MyNavigation_Navigated( object sender, ShellNavigatingEventArgs e )
     {
         // This blows up. Even the debugger cannot access the value, although it appears to have the correct type.
         ContentPage viewBase = (ContentPage)CurrentPage;
     }
 }

 public partial class App : Application
 {
     public App()
     {
         InitializeComponent();
         MainPage = new MyNavigation();
     }
 }

 public class HomeView : ContentPage
 {
     public HomeView()
     {
         Title = "Home Tab";
     }
 }
    
 public class SettingsView : ContentPage
 {
     public SettingsView()
     {
         Title = "Settings Tab";
     }
 }
    
 public class ModalView : ContentPage
 {
     public ModalView()
     {
         Title = "Modal View";
         Shell.SetPresentationMode( this, PresentationMode.Modal );
     }
 }

I can navigate without error between the two screens in the tab bar. However, when I navigate to the modal screen, I am
unable to access the value of CurrentPage in the Shell Navigated event. It even crashes the debugger.

If I remove the call to SetPresentationMode(), the error doesn't happen.

I am assuming this is a bug and I have raised it with the Xamarin team but they seem to be strangely quiet about it. (I have
heard nothing for over two weeks; guess everyone is now over on MAUI.)

Does anyone know if this really is a bug? If so, is it likely to be fixed or is there something fundamentally wrong with what
I am trying to do? The Shell class is advertised as being able to do pretty much any navigation you want so I will be disappointed to say the least if I cannot do this.

Can anyone think of a workaround that will allow me to access the current page inside the Shell Navigated event?

















dotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

KyleWang-MSFT avatar image
1 Vote"
KyleWang-MSFT answered PatrickRyder commented

Hi PatrickRyder,

Welcome to our Microsoft Q&A platform!

You didn't provide any code about how to open a ModalView, so I'm assuming here that you opened a ModalView via a button in HomeView.

In my test, there is no crash. But Navigated is not triggered when "PushModalAsync" is called to open a ModalView. When I used "PushAsync" instead, everything works fine, the Navigated is triggered and I can get the ModalView instance.
ModalView.cs

 public class ModalView : ContentPage
 {
     public ModalView()
     {
         Title = "Modal View";
         Shell.SetPresentationMode(this, PresentationMode.Modal);
     }
 }

HomeView.cs

 public class HomeView : ContentPage
 {
     public HomeView()
     {
         Button btn = new Button { Text = "Modal" };
         btn.Clicked += HomeView_Clicked;
    
         Content = new StackLayout
         {
             Children = {
                 btn
             }
         };
    
         Title = "Home Tab";
     }
     private void HomeView_Clicked(object sender, EventArgs e)
     {
         ModalView modalView = new ModalView();
         App.Current.MainPage.Navigation.PushAsync(modalView);
     }
    
     protected override void OnAppearing()
     {
         base.OnAppearing();
         ContentPage viewBase = (ContentPage)this;
         Console.WriteLine("=====" + viewBase.Title + "=====");
     }
 }

Regards,
Kyle


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@KyleWang-MSFT

Thank you for your reply.

Yes, I should have included the code that triggers the call to my navigation. It was unclear of me to assume that readers would work out that my navigation to the modal screen is triggered by a call to the following line in my Shell code:

 public async Task NavigateAsync( string screenName ) => await GoToAsync( screenName );

So are you saying that I can call PushAsync(), get a Navigated event, and then display the target screen modally (i.e. without the tab bar or back navigation links being displayed)?

If I do this, how can I get back to the home page? The whole reason I switched to the new navigation is because I could not pop-to-root from a modal screen.

  • Patrick


0 Votes 0 ·

@PatrickRyder To back to HomeView from modal, for Android, you can press virtual back button. It's easy. For iOS, you need to set the Page.ModalPresentationStyle bindable property to a UIModalPresentationStyle enumeration value. So add the following line in ModalView.

 On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.PageSheet);

For more info, you can refer to document: Modal Page Presentation Style on iOS.


1 Vote 1 ·

@KyleWang-MSFT

I'll check that out. Thank you.

I do need to be able to do something like pop-to-root, though, because my application has parts that are wizard style, so I will end up with something like this:

HomeTab -> ModalA -> ModalB -> ModalC

Sometimes, from, say, ModalC, I will need to go all the way back to HomeTab. I also really do need the Navigated event, because sometimes I will go back from ModalC to ModalB and on iOS I was not getting an OnAppearing() event for this.

Guess, I will just have to keep experimenting.

  • Patrick


0 Votes 0 ·
Show more comments