MasterDetail with Prism, how to?

Issue

I am trying to test and example with MasterDetail. You can see the code in:

https://github.com/jrariasf/MD8/tree/master/MD8

The Master have 5 buttons to access to 4 detail pages (Home, MainPage, ViewA, ViewB and ViewC).

From ViewA, with 2 buttons I am able to load ViewB and ViewC

But I am not able to do that pushing a button in hambubrger menu then load the detail page adequated.

It only works if I put an absolute path in the CommandParameter in “PrismMasterDetailPage.xaml”:

<?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:prism"http://prismlibrary.com"
                  prism:ViewModelLocator.AutowireViewModel"True"
                  x:Class"MD8.Views.PrismMasterDetailPage">

    <MasterDetailPage.Master>
        <ContentPage Title"Menu">
            <StackLayout Padding"20">
                <!-- TODO: // Update the Layout and add some real menu items  -->
                <Button Text"Home" Command"{Binding NavigateCommand}" CommandParameter"/PrismMasterDetailPage/NavigationPage/ViewA" />
            <Button Text"MainPage" Command"{Binding NavigateCommand}" CommandParameter"/NavigationPage/MainPage" />
            <Button Text"ViewA" Command"{Binding NavigateCommand}" CommandParameter"../ViewA" />
            <Button Text"ViewB" Command"{Binding NavigateCommand}" CommandParameter"./ViewB" />
            <Button Text"ViewC" Command"{Binding NavigateCommand}" CommandParameter"ViewC" />
            </StackLayout>
        </ContentPage>
    </MasterDetailPage.Master>

</MasterDetailPage>

Then, in “PrismMasterDetailPageViewModel.cs”

void ExecuteCommandName(string page)
{
    Console.WriteLine("PrismMasterDetailPageViewModel - ExecuteCommandName() Vamos a {0}", page);

    _navigationService.NavigateAsync(page);
}

If I am in “/PrismMasterDetailPage/NavigationPage/ViewA”, what I have to do to unload ViewA and load ViewB ?

For example, in App.xaml.cs the code is:

await NavigationService.NavigateAsync("PrismMasterDetailPage/NavigationPage/ViewA");

Then, execute the app on android emulator, push buttons of hamburger menu and the result it is not as I expected. Pressing Home button, the _navigationService.GetNavigationUriPath() returns: /PrismMasterDetailPage/NavigationPage/ViewA/NavigationPage?useModalNavigationtrue/ViewA

why?

If I press button ViewA or ViewB or ViewC, it don’t show anything. But the OnNavigatedFrom() method is called on each View*ViewModel.cs

What is wrong?

Thanks!!

Solution

One fo the first things you need to do is understand where you are Navigating from. Navigation in Xamarin.Forms is very dependent on where you are Navigating from. Remember that without Prism you would do something like this:

var mdp  new MyMasterDetailPage
{
    Detail  new NavigationPage(new ViewA)
};

In order to achieve a Hamburger Menu with Prism you typically would want a MasterDetailPage as the Application’s Main Page. The next segment in the Navigation Uri must be a NavigationPage and the following page would generally be a ContentPage.

<Button Text"Home" 
        Command"{Binding NavigateCommand}" 
        CommandParameter"/PrismMasterDetailPage/NavigationPage/ViewA" />

Ok so looking at this first one, this is generally what you would use when navigating from the PrismApplication which is why it works.

<Button Text"MainPage" 
        Command"{Binding NavigateCommand}" 
        CommandParameter"/NavigationPage/MainPage" />

Looking at this one, this is really close to what you do want except you are doing an absolute navigation which means that you are resetting the Application.MainPage. What you actually need is a relative Uri because you are navigating from the MasterDetailPage.

<Button Text"ViewA" 
        Command"{Binding NavigateCommand}" 
        CommandParameter"../ViewA" />

This is completely wrong because ../{path} is only supported from within a NavigationPage and you are in a MasterDetailPageā€¦

<Button Text"ViewB" 
        Command"{Binding NavigateCommand}" 
        CommandParameter"./ViewB" />

This is just not supported by Prism at all.

<Button Text"ViewC" 
        Command"{Binding NavigateCommand}" 
        CommandParameter"ViewC" />

This is setting the MasterDetailPage.Detail like:

mdp.Detail  new ViewC()

Of course as I mentioned above you need it to be

mdp.Detail  new NavigationPage(new ViewC());

Answered By – Dan Siegel

Leave a Comment