Best way to use mixed navigation?

MulflarMulflar ESUniversity ✭✭

I'm making a Xamarin forms app with mixed masterdetail and navigation design.
The app starts with a login page, then goes to a Masterdetail page with a home, the home icons and menu options navigate to tab pages, who go to detail pages...
Yeah I know it's a bit weird...

Currently I have a navigation service that works (fortunatelly). I got the point from here https://github.com/dotnet-architecture/eShopOnContainers the problem is, that it's growing to a "case" navigation I don't like to much.

The current code looks like:

    private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
    {
        Page page = CreatePage(viewModelType, parameter);

        if (page is Login_View || page is Home_View)
        {
            Application.Current.MainPage = page;
        }
        else if(page is Type1_View || page is Home_ViewDetail || page is Type2_View)
        {
    //the lateral menu is a expandable listview
            ((Home_ViewModel)((MasterDetailPage)Application.Current.MainPage).BindingContext).CLoseSubMenus();
            ((MasterDetailPage)Application.Current.MainPage).Detail = new NavigationPage(page);
            ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;               
        }
        else
        {
            var navigationPage = ((NavigationPage)((MasterDetailPage)App.Current.MainPage).Detail);
            if (navigationPage != null)
            {
                ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
                await navigationPage.PushAsync(page);
            }
        }

        var vm = page.BindingContext as Base_ViewModel;

        await (page.BindingContext as Base_ViewModel).InitializeAsync(parameter);
    }

I'm afraid about the future of the app, as I think as more cases will come, more complex will this function be.
Any refactor sugestion?

Best Answer

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited September 29 Accepted Answer

    @Mulflar - Create a subclass of ContentPage. Add a property to the subclass, with the property being the thing that you test in InternalNavigateToAsync . As you have an if/else/else, that property currently needs to return one of three values that you then switch on.

    You could take that a step further, by having three subclasses of ContentPage, with your pages each subclassing the appropriate one of the three. The three subclasses do the appropriate navigation themselves.

    Or you could have your pages implement one of three interfaces (the interfaces can be empty), then have InternalNavigateToAsync act based on which interface has been implemented.

    Of the three, I'd lean against the second one, as I prefer to keep the navigation out of the page class.

Answers

  • JohnHardmanJohnHardman GBUniversity ✭✭✭✭✭
    edited September 29 Accepted Answer

    @Mulflar - Create a subclass of ContentPage. Add a property to the subclass, with the property being the thing that you test in InternalNavigateToAsync . As you have an if/else/else, that property currently needs to return one of three values that you then switch on.

    You could take that a step further, by having three subclasses of ContentPage, with your pages each subclassing the appropriate one of the three. The three subclasses do the appropriate navigation themselves.

    Or you could have your pages implement one of three interfaces (the interfaces can be empty), then have InternalNavigateToAsync act based on which interface has been implemented.

    Of the three, I'd lean against the second one, as I prefer to keep the navigation out of the page class.

  • MulflarMulflar ESUniversity ✭✭

    @JohnHardman said:
    @Mulflar - Create a subclass of ContentPage. Add a property to the subclass, with the property being the thing that you test in InternalNavigateToAsync . As you have an if/else/else, that property currently needs to return one of three values that you then switch on.

    You could take that a step further, by having three subclasses of ContentPage, with your pages each subclassing the appropriate one of the three. The three subclasses do the appropriate navigation themselves.

    Or you could have your pages implement one of three interfaces (the interfaces can be empty), then have InternalNavigateToAsync act based on which interface has been implemented.

    Of the three, I'd lean against the second one, as I prefer to keep the navigation out of the page class.

    At the end I went for the multiple interface option because not all are ContentPages I have also TabbedPages and MasterDetail Pages. I make 2 interfaces and let the code like this:

      Page page = CreatePage(viewModelType, parameter);
    
            if(page is SimpleNavType)
            {
        //login and main
                Application.Current.MainPage = page;
            }
            else if(page is DetailNavType)
            {
        //detail pages of the MasterDetail
                ((Home_ViewModel)((MasterDetailPage)Application.Current.MainPage).BindingContext).CLoseSubMenus();
                ((MasterDetailPage)Application.Current.MainPage).Detail = new NavigationPage(page);
                ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
            }
            else
            {
        //Navigation Pages
                var navigationPage = ((NavigationPage)((MasterDetailPage)App.Current.MainPage).Detail);
                if (navigationPage != null)
                {                   
                    await navigationPage.PushAsync(page);
                }
            }
    
Sign In or Register to comment.