2
votes

I'm using Prism.Forms 6.3 in a Xamarin.Forms 2.3.4.247 project. I'm having a hard time tracking why the back arrow button isn't visible when I navigate to a details page within a Master/Detail setup.

I can navigate to the Pages just fine, but the back-button never shows up. Instead, the hamburger menu icon is always visible. This is my "Master" page.

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:FloatSink.Apps.Mobile.Views.ValueConverters"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="FloatSink.Apps.Mobile.Views.MainPage"
             BackgroundColor="Blue">

    <MasterDetailPage.Master>
        <ContentPage Title="Menu">
            <StackLayout Padding="40">
                <Label Text="Hello" />
                <Button Text="Feed" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/FeedPage" />
                <Button Text="Options" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/OptionsPage" />
            </StackLayout>
        </ContentPage>
    </MasterDetailPage.Master>
</MasterDetailPage>

This is two of my Detail pages.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FloatSink.Apps.Mobile.Views.FeedPage">

    <Label Text="Hello from Feed Page!" />
</ContentPage>

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FloatSink.Apps.Mobile.Views.OptionsPage">

    <Label Text="Hello from Options Page!" />
</ContentPage>

I navigate to it using the CommandParameter specified in my Master page, using the navigation service in the MainPageViewModel.

private void NavigateToPage(string uri)
{
    this.navigationService.NavigateAsync(uri);
}

I've setup my NavigationPage like this during the startup of the app so I land on the FeedPage first, then I can navigate to the OptionsPage.

public class App : PrismApplication
{
    public App(IPlatformInitializer dependencyRegister) : base(dependencyRegister) { }

    protected override void OnInitialized()
    {
        base.NavigationService.NavigateAsync("MainPage/NavigationPage");
    }

    protected override void RegisterTypes()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<NavigationRegistration>();
        builder.RegisterModule<ServicesRegistration>();
        base.Container.RegisterTypeForNavigation<NavigationPage>();
        // This is deprecated but we have to wait for Prism.Autofac to update itself
        builder.Update(base.Container);
    }
}

The DI registrations associated with navigation are done in this module:

internal class NavigationRegistration : Module
{
    /// <summary>
    /// Load the navigation related types into the given builder.
    /// </summary>
    /// <param name="builder">Container Builder that will be turned into the final IOC Container</param>
    protected override void Load(ContainerBuilder builder)
    {
        // Register the NavigationPage in Xamarin with the Prism Navigation system.
        //builder.RegisterType<NavigationPage>().AsSelf();
        //PageNavigationRegistry.Register(nameof(NavigationPage), typeof(NavigationPage));

        // Get all of the Types that represent a View in our assembly for DI and navigation registration
        // If start-up time ever becomes an issue, we can replace this assembly scan with explicit registrations.
        Type[] viewTypes = base.ThisAssembly.GetTypes().Where(type => type.IsAssignableTo<Page>()).ToArray();

        // Iterate over each discovered View Type and register it with the navigation system and DI container.
        for(int index = 0; index < viewTypes.Length; index++)
        {
            Type viewType = viewTypes[index];
            builder.RegisterType(viewType).Named<Page>(viewType.Name);

            // If we ever need to disconnect a view name from its Type name, we can do so here.
            // We would build a custom attribute to decorate the view with, pull the attribute from the Type
            // and register the Type with the attribute value.
            PageNavigationRegistry.Register(viewType.Name, viewType);
        }
    }
}

Again I can each one of my detail pages without problem, the hamburger menu exists and I can open the Master page to view my buttons used for navigating. I just can't navigate backwards once I'm there. Is that something I'm supposed to wire up myself?

4
I'm not sure I'm reading your question right but it sounds like this is normal behavior. In my (short) experience with XF/Prism, every navigation from the master is a beginning of the stack. If you were to add another page, e.g. from Master->PageA->PageB, I would expect Page A to have the hamburger menu but going to PageB would give you the back arrow.erin
Thanks! That was exactly what my problem was. I was initially navigating to MainPage/NavigationPage/FeedPage and wanted to go to a child View called Foo. I was navigating as NavigationPage/FooPage. Changing it to NavigationPage/FeedPage/FooPage fixed it. I've got my back button when I land on FooPage woot!Johnathon Sullinger
Yay! I'll add it as an answer. :)erin

4 Answers

2
votes

I'm not sure I'm reading your question right but it sounds like this is normal behavior. In my (short) experience with XF/Prism, every navigation from the master is a beginning of the stack. If you were to add another page, e.g. from Master->PageA->PageB, I would expect Page A to have the hamburger menu but going to PageB would give you the back arrow.

1
votes

For using NavigationPage inside uri you should register it for navigation in the App.xaml.cs:

protected override void RegisterTypes()
{
    // your registrations
    Container.RegisterTypeForNavigation<NavigationPage>();
}

I most cases it is the reason.

0
votes

To Navigate To Master Page "/MasterPage/NavigationPage/ViewA"

To Navigate out of Master Page from ViewA and with back button "ViewB"

-2
votes

You need to start your app with MainPage = new NavigationPage(new StartPage()); That is how it is solved in normal situation. So maybe try to register your MainPage wrapped in a NavigationPage.