Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MvvmCross sidebar navigation for MvvmCross 5.x

I with to implement two types of navigation for my app, sidebar navigation and parent-child navigation at the same time. My app starts with hamburger (sidebar) menu.

First item in sidebar menu should perform reset of the navigation stack and open home view. Home view controller should start a root stack navigation so every button on the home view should open a new view, button on a new view should open another view etc.

Every other item in sidebar menu should open a new view as a dialog.

I'm using MvvmCross 5.x, and there is no sample compatible with 5.x version. Is there anyone who can point me to a usable sample?

like image 462
Hrvoje Matić Avatar asked Dec 14 '22 22:12

Hrvoje Matić


1 Answers

First of I assume you are trying to implement this for iOS. In case of Android you could simply use the Navigation Drawer.

The sample on iOS is not yet converted to MvvmCross 5.x (I will start doing so a.s.a.p.), however this should be trivial. Let me try to walk you through it:

  1. Make sure you add the MvvmCross iOS Support package to your iOS project: Install-Package MvvmCross.iOS.Support -Version 5.0.2 (or use the GUI)
  2. Configure your iOS project to use the MvxSidebarPresenter by adding the following code to the Setup class in your iOS project:

    protected override IMvxIosViewPresenter CreatePresenter()
    {
        return new MvxSidebarPresenter((MvxApplicationDelegate)ApplicationDelegate, Window);
    }
    
  3. Create a view controller which acts as you flyout menu and decorate it with the MvxSidebarPresentationAttribute. This view controller will act as your menu. You can (or better should) link it to a view model which will handle the navigation part (when the user selects a menu item). This view controller could look something like this:

    [MvxSidebarPresentation(MvxPanelEnum.Left, MvxPanelHintType.PushPanel, false)]
    public class LeftPanelView : MvxViewController<LeftPanelViewModel>
    {
        ...
    }
    
  4. To make sure your home view act as a root controller simply add the MvxSidebarPresentationAttribute to the home view controller and make sure the property Panel is set to Center, HintType is set to ResetRoot and ShowPanel is set to true), like so:

    [MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.ResetRoot, true)]
    public class HomeView : MvxViewController<HomeViewModel>
    {
        ...
    }
    
  5. For all child views (opened from the home view) make sure you set the MvxSidebarPresentationAttribute with the property Panel set to Center, HintType set to PushPanel and depending if you want to display the menu button on the child pages set the ShowPanel to true or false, like so:

    [MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.PushPanel, true)]
    public class ChildView : MvxViewController<ChildViewModel>
    {
        ...
    }
    
  6. The last step is to setup the view controller for all other buttons in the menu. These can simply be decorated with the MvxModalPresentationAttribute attribute to open them as a dialog (detailed documentation can be found here). An example could look something like this:

    [MvxModalPresentation(ModalPresentationStyle = UIModalPresentationStyle.OverFullScreen, ModalTransitionStyle = UIModalTransitionStyle.CrossDissolve)]
    public partial class ModalView : MvxViewController<ModalViewModel>
    {
        ...
    }
    

To open the different views you can make use of the new navigation service in MvvmCross. To do so simply allow the MvvmCross IoC container to inject an instance into your view models constructor (more details can be found here):

public class HomeViewModel : MvxViewModel
{
    private readonly IMvxNavigationService _navigationService;

    public HomeViewModel(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService ?? throw new ArgumentNullException(nameof(navigationService));
    }
}

EDIT 1: To be able to show an icon on as menu button, you'll need to implement the IMvxSidebarMenu interface on the view controller that makes up the menu (see step 3). By implementing this interface you can override the default behaviour of the menu, and example can be found here (which is part of the demo MvvmCross XamarinSidebar application).

EDIT 2: I have mistakenly suggested that you can show the menu (or it's icon) button on a child view which is pushed on the navigation stack. This is not the case, child views that are pushed on the stack will not show the menu button. In these cases the ShowPanel property is ignored completely.

EDIT 3: There is a way to accomplish that pattern entirely. We can customize stack navigation UI so we can mimic something like Android toolbar. This approach works and it basically requires us to make navigation bar hidden and create our custom toolbar that has hamburger menu, back button and other buttons and put it in the upper part of the child view. Here is the code needed for close and back buttons:

public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            NavigationController.NavigationBarHidden = true;

            btnClose.TouchUpInside += (object sender, EventArgs e) =>
            {
                NavigationController.NavigationBarHidden = false;
                NavigationController.PopViewController(false);
            };

            btnShowMenu.TouchUpInside += (object sender, EventArgs e) =>
            {
                var sideMenu = Mvx.Resolve<IMvxSidebarViewController>();
                sideMenu?.Open(MvxPanelEnum.Left);
            };
        }
like image 96
Maurits van Beusekom Avatar answered Dec 28 '22 07:12

Maurits van Beusekom