Search code examples
c#iphonexamarin.iosmvvmcross

SideMenu for mvvmCross


Tying to implement side menu for Xamarin.iOS app, but got warning in console:

mvx:Warning: 0.25 No sidemenu found. To use a sidemenu decorate the viewcontroller class with the 'MvxPanelPresentationAttribute' class and set the panel to 'Left' or 'Right'.

Steps

1) Create base class for menu (from sample)

public class BaseMenuViewController<T> : MvxViewController<T>, IMvxSidebarMenu where T : class, IMvxViewModel
{
    public virtual UIImage MenuButtonImage => UIImage.FromBundle("burger");

    public virtual bool AnimateMenu => true;
    public virtual float DarkOverlayAlpha => 0;
    public virtual bool HasDarkOverlay => false;
    public virtual bool HasShadowing => true;
    public virtual bool DisablePanGesture => false;
    public virtual bool ReopenOnRotate => true;

    private int MaxMenuWidth = 300;
    private int MinSpaceRightOfTheMenu = 55;

    public int MenuWidth => UserInterfaceIdiomIsPhone ?
        int.Parse(UIScreen.MainScreen.Bounds.Width.ToString()) - MinSpaceRightOfTheMenu : MaxMenuWidth;

    private bool UserInterfaceIdiomIsPhone
    {
        get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
    }

    public virtual void MenuWillOpen()
    {
    }

    public virtual void MenuDidOpen()
    {
    }

    public virtual void MenuWillClose()
    {
    }

    public virtual void MenuDidClose()
    {
    } 
}

2) Implement VisibleView (First one that will be visible)

[MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.ResetRoot, true)]
public partial class ContentViewController : MvxViewController<ContentViewModel>
{
    public ContentViewController()
        : base("ContentViewController", null)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        View.BackgroundColor = UIColor.Purple;
        this.ViewModel.Show<MenuViewModel>();
    }
}

3) Implement MenuElementViewController (SideMenu)

[Register("MenuViewController")]
[MvxSidebarPresentation(MvxPanelEnum.Left, MvxPanelHintType.PushPanel, false)]
public class MenuViewController : BaseMenuViewController<MenuViewModel>
{
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        this.View.BackgroundColor = UIColor.Red;
    }
}

4) Add presenter for SideMenu in Setup

protected override IMvxIosViewPresenter CreatePresenter()
{
    return new MvxSidebarPresenter((MvxApplicationDelegate)ApplicationDelegate, Window);
}

Expected behavior

Should see controller from point 1 with burger button

Actual behavior

Controller from point1 become visible but without burger button, Controller from point2 not initialized, Warning in console about missed decoration for class, but as u see they are present (also warnings deprecated and need to be updated - check source code - searching done for correct type, but warning has old message )

Configuration

MvvmCross v 5.0.6

  • MvvmCross
  • MvvmCross.Core
  • MvvmCross.Binding
  • MvvmCross.iOS.Support
  • MvvmCross.iOS.Support.XamarinSidebar
  • MvvmCross.Platform
  • SidebarNavigation

Also saw this post while looking for error - recheck and looks like everything is fine, but not work.

Warning log:

mvx:Diagnostic: 0.21 Setup: Secondary end

mvx:Diagnostic: 0.21 Showing ViewModel ContentViewModel iOSNavigation:Diagnostic: 0.21 Navigate requested

mvx:Warning: 0.23 No sidemenu found. To use a sidemenu decorate the viewcontroller class with the 'MvxPanelPresentationAttribute' class and set the panel to 'Left' or 'Right'.

I also expect to see breakPoint stop in ViewDidload for MenuViewController when call this.ViewModel.Show<MenuViewModel>(); but it's never triggered, in same moment model for this controller created.

Can someone advice what was done incorrect?


EDIT

I was able to setup new empty project with sidebar and it's work as expected. But same code not work in my current projects - I don't know why decorated attributes are not read as expected....


Solution

  • Spend 2 days to figure out the reason - the issue related to detection and parsing decorator attributes.

    I have few projects that share codebase between each other, and due to some reason [MvxSidebarPresentation(MvxPanelEnum.Left, MvxPanelHintType.PushPanel, false)] is not taken in to account if it placed in shared project but not in project itself. In same moment

    [MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.ResetRoot, true)]
    [MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.ResetRoot, true, MvxSplitViewBehaviour.Master)]
    [MvxSidebarPresentation(MvxPanelEnum.Center, MvxPanelHintType.PushPanel, true, MvxSplitViewBehaviour.Detail)]
    

    works as expected.

    Workaround -> subclass shared menuClass (with MvxPanelEnum.Left) in each project where it should be used.

    Not sure if this issue related to mvvmCross lib or to Xamarin.