0

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....

hbk
  • 10,908
  • 11
  • 91
  • 124

2 Answers2

1

That trace is triggered by this piece of code in the MvxSidebarViewController.

    protected virtual void SetupSideMenu()
    {
        var leftSideMenu = ResolveSideMenu(MvxPanelEnum.Left);
        var rightSideMenu = ResolveSideMenu(MvxPanelEnum.Right);

        if (leftSideMenu == null && rightSideMenu == null)
        {
            Mvx.Trace(MvxTraceLevel.Warning, $"No sidemenu found. To use a sidemenu decorate the viewcontroller class with the 'MvxPanelPresentationAttribute' class and set the panel to 'Left' or 'Right'.");
            AttachNavigationController();
            return;
        }

        // ...
    }

So Mvvmcross is failing to resolve the SideMenu view controllers marked with the attributes you have used above. I'd suggest removing all of the MvvmCross nugets and nuking the bin and obj folders.

Possibly try adding a constructor to the MenuViewController might help.

If all that fails I'd try building the classes exactly how they are in the test project, I noticed your ContentViewController doesn't inherit from a base class like it does in the project. I know this shouldn't really be relevant but what I've found from my experiments with the sidebar classes is it's very particular with the setup of ViewControllers and nested view controllers.

I did away with the MvvmCross siderbar nuget altogether and just used the XamarinSidebar nuget directly, I used MvxSidebarViewController as a starting point to create my own implementation, I wasn't particularly keen on the attribute setup and I like to handle the navigation myself rather than use ShowViewModel or the new navigation system.

Hope some of that helps.

Mark Silver
  • 412
  • 6
  • 15
  • thanks - I already try to remove/add/update reinstall lib, recreate all classes, rename, clean, remove bin/ and obj/ folders, ful clean of project - result every time same.... In same moment i copy-paste code in separate project and it just work.. Looks like problem with decoration attribute detection (pleasee see my edit with sample link) – hbk Jul 14 '17 at 10:16
  • also add/remove constructors, direct subclass from Mvx classess not help – hbk Jul 14 '17 at 10:18
  • Interesting might be a Xamarin bug, try googling the attributes detection. – Mark Silver Jul 14 '17 at 10:18
  • already started... if i found root cause - i will post it here, thanks (honestly not very familiar with c#) – hbk Jul 14 '17 at 10:19
  • If all else fails you could just do what I did and make your own implementation using the XamarinSidebar nuget. – Mark Silver Jul 14 '17 at 10:20
  • preffered is mvvmCross solution, thus i have project with mvvmCross as main lib and so we targeted to use mvvmCross navigation approach, but of cause if i not found any solution i will try it – hbk Jul 14 '17 at 10:23
  • Yes, I'm saying you could write your own MvvmCross navigation code wrapped around the sidebar stuff. Good luck! – Mark Silver Jul 14 '17 at 10:27
0

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.

hbk
  • 10,908
  • 11
  • 91
  • 124