Navigate inside TabbedPage (MVVM)

Hi guys, I have a problem that maybe many of you faced but even after browsing the web and this forum I couldn't fix it...

I have a TabbedPage that contains 2 children, a ContentPage (Page1) and a NavigationPage that embedded another ContentPage (Page2)

What I want is to be able to navigate inside Page2 and keeping my Tabbar on every page. For now I'm able to push/pop in Page2 but all the subpages doesn't have the tabbar. Only Page 1 and 2 has it.

I found that I had to embedded my MainPage in a NavigationPage in my App.cs
MainPage = new NavigationPage(new MainPage());
but even with these it doesn't change anything and when I remove it, I have a PushAsync is not supported globally on Android, please use a NavigationPage on both iOS and Android.

So I just don't know where do I have to put my NavigationPage(s) now.

I try to do things exactly like in this exemple
https://github.com/xamarin/xamarin-forms-samples/tree/master/Navigation/TabbedPageWithNavigationPage but they are not using MVVM so it's kind of "easier" for them and it doesn't really help me.

For the navigation, I created a service that create a page from the viewModel and use the Application.Current.MainPage.Navigation to push and pop.

If anyone can help...

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    If you used the architecture as the sample's, the tab bar will display on each of the subpages. Here is my screenshot:

    if you want to know how to push to a new page in your view model. You can pass your Navigation to your view model and then consume it there. Refer to my thread here: https://forums.xamarin.com/discussion/comment/382559/#Comment_382559

  • KingamattackKingamattack Member ✭✭

    I think this is because, them (and you in your sample) are directly passing a page in the Navigation.PushAsync but in my case I try to do it by passing a ViewModel as parameter.

    I have a custom implementation of INavigationService that create a Page based on the ViewModel I passed and then push that page using Application.Current.MainPage.Navigation.PushAsync(destinationPage). But even with this, I still don't have the tab in the pages that I'm pushing

  • LandLuLandLu Member, Xamarin Team Xamurai

    but in my case I try to do it by passing a ViewModel as parameter.

    How did you make it?
    If we can access navigation in the corresponding view model why do we need to use Application.Current.MainPage? Its Navigation may be not your current page's navigation.

  • KingamattackKingamattack Member ✭✭

    In my App.cs I register each ViewModels with a Page thanks to MVVMLight register method. navigationService.Register<MainViewModel, MainPage>(false)

    Then, in all my ViewModels, when I want to push from a page to another, I just have to Navigation.PushAsync<DestinationViewModel>(parameters). And here is the implementation of PushAsync

    public async Task PushAsync<TViewModel>(bool animated, object parameter = null)
            {
                try
                {
                    var destinationPage = CreateView(typeof(TViewModel)) as Page;
                    NavigationExtensions.SetNavigationArgs(destinationPage, parameter);
                    await Application.Current.MainPage.Navigation.PushAsync(destinationPage, animated);
                }
                catch (Exception ex)
                {
                    loggerService.TraceError($"[NavigationService PushAsync] {ex.Message}");
                }
            }
    
  • LandLuLandLu Member, Xamarin Team Xamurai

    I am using native Forms library. Maybe, MVVMLight changes the structure. I've no idea about that. You should raise issues under their github or official website.

  • KingamattackKingamattack Member ✭✭

    I checked your sample in the link https://forums.xamarin.com/discussion/comment/382559/#Comment_382559

    Do you instantiate your INavigation somewhere? In App.cs ? or its instantiated by itself?

  • LandLuLandLu Member, Xamarin Team Xamurai

    @Kingamattack Each page has its own view model. And we set its view model in its constructor. I used the code below to pass the navigation to view model:

    public PlaylistsPage()
    {
       InitializeComponent();
       BindingContext = new PlaylistsVm(Navigation);
    }
    

    PlaylistsPage is a content page and PlaylistsVm is its binding context(view model).

  • KingamattackKingamattack Member ✭✭

    Yeah but in my case, I passed the ViewModel directly in XAML like this
    MainPage.xaml

        <NavigationPage  IconImageSource="ic_tab_car" Title="Title" >
            <x:Arguments>
                <pages:MapHome BindingContext="{Binding MapHomeViewModel}"/>            
            </x:Arguments>
        </NavigationPage>
    
        <NavigationPage IconImageSource="ic_menu" Title="Title 2">
            <x:Arguments>
                <pages:PlusPage BindingContext="{Binding PlusViewModel}"/>
            </x:Arguments>
        </NavigationPage>    
    </TabbedPage>
    

    MainPage.xaml.cs
    public partial class MainPage : TabbedPage
    {
    public MainPage()
    {
    InitializeComponent();
    BindingContext = SimpleIoc.Default.GetInstance();
    }
    }

    The question now is, in my App.cs do I need to embedded my MainPage (which is a TabbedPage) into a NavigationPage? Cause if I don't I still have the PushAsync is not supported globally on iOS, please use a NavigationPage.

    What I will try to do, is to have a NavigationService class that host a INavigation property which is equal to my mainPage navigation. And from there, I could change the Page to ViewModel and use Navigation to push just like you

Sign In or Register to comment.