mvvmCross 的侧边菜单

SideMenu for mvvmCross

正在为 Xamarin.iOS 应用实现侧边菜单,但在控制台中收到警告:

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

步骤

1) 为菜单创建基础 class(来自 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) 实现 VisibleView(第一个可见的)

[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) 实施 MenuElementViewController(侧边菜单)

[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) 在设置中为 SideMenu 添加演示者

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

预期行为

应该从点 1 看到带有汉堡按钮的控制器

实际行为

点 1 的控制器变得可见但没有汉堡按钮, 来自 point2 的控制器未初始化, 控制台中关于 class 错过装饰的警告,但如您所见,它们存在(警告也已弃用,需要更新 - check source code - searching done for correct type, but warning has old message

配置

MvvmCross v 5.0.6

在查找错误时也看到 - 重新检查,看起来一切正常,但无法正常工作。

警告日志:

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

我还希望在调用 this.ViewModel.Show<MenuViewModel>(); 时在 ViewDidload 中看到 MenuViewController 的断点停止,但它从未被触发,同时创建了此控制器的模型。

谁能告诉我做错了什么?


编辑

我能够设置 new empty project with sidebar 并且它按预期工作。但是相同的代码在我当前的项目中不起作用 - 我不知道为什么没有按预期读取装饰属性....

该跟踪是由 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;
        }

        // ...
    }

因此 Mvvmcross 无法解析标有您在上面使用的属性的 SideMenu 视图控制器。我建议删除所有 MvvmCross nugets 并删除 binobj 文件夹。

可能尝试向 MenuViewController 添加构造函数可能会有所帮助。

如果所有这些都失败了,我会尝试构建 classes 完全按照它们在测试项目中的样子,我注意到你的 ContentViewController 不是从基础 class 继承的就像在项目中一样。我知道这不应该真正相关,但我从侧边栏的实验中发现 classes 是 ViewControllers 和嵌套视图控制器的设置非常特别。

我完全放弃了 MvvmCross siderbar nuget,直接使用了 XamarinSidebar nuget,我使用 MvxSidebarViewController 作为创建我自己的实现的起点,我不是特别热衷于属性设置和我喜欢自己处理导航而不是使用 ShowViewModel 或新的导航系统。

希望对您有所帮助。

花2天时间找出原因——检测和解析装饰器属性的问题。

我有几个项目彼此共享代码库,并且由于某种原因 [MvxSidebarPresentation(MvxPanelEnum.Left, MvxPanelHintType.PushPanel, false)] 如果它放置在共享项目中但不在项目本身中,则不会被考虑在内。在同一时刻

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

按预期工作。

解决方法 -> 在每个项目中应该使用它的子类共享 menuClass(MvxPanelEnum.Left)。

不确定此问题是否与 mvvmCross 库或 Xamarin.