MvvmCross 迁移导致 Xamarin 自定义 iOS 视图演示器问题

问题描述

在创建 CustomIosViewPresenter(MvxIosViewPresenter 类型)时,在 MVVMCross 5.x 中,有一个 Show 覆盖,我可以使用它来获取 IMvxIosView 以便更新使用 viewmodel 中的 PresentationValues 的 UIViewController 呈现样式。

我有这个代码并且它有效:

// Worked before
public override void Show(IMvxIosView view,MvvmCross.viewmodels.MvxviewmodelRequest request)
{
    if (request.PresentationValues != null)
    {
        if (request.PresentationValues.ContainsKey("NavigationMode") &&
            request.PresentationValues["NavigationMode"] == "WrapInModalWithNavController")
        {
            var vc = view as IModalPresentation;
            vc.ModalPresentationAttribute = new MvxModalPresentationAttribute
            {
            WrapInNavigationController = true,ModalPresentationStyle = UIModalPresentationStyle.OverFullScreen,ModalTransitionStyle = UIModalTransitionStyle.CoverVertical
            };
        }
    }
    base.Show(view,request);
}

但是在迁移到 MvvmCross 7.1 之后,旧的覆盖不再起作用,我必须改用它,但是没有视图传递到 Show 覆盖中,我如何获得它? 我在下面尝试了此代码,但 view 为空且无法以这种方式进行转换 var view = viewType as IMvxIosView;

// Doesn't work Now
public override Task<bool> Show(MvxviewmodelRequest request)
{
    if (request.PresentationValues != null)
    {
        if (request.PresentationValues.ContainsKey("NavigationMode") &&
            request.PresentationValues["NavigationMode"] == "WrapInModalWithNavController")
        {
            var viewsContainer = Mvx.IoCProvider.Resolve<IMvxViewsContainer>();
            var viewType = viewsContainer.GetViewType(request.viewmodelType);
            var view = viewType as IMvxIosView;
            
            var vc = view as IModalPresentation;
            vc.ModalPresentationAttribute = new MvxModalPresentationAttribute
            {
                WrapInNavigationController = true,ModalTransitionStyle = UIModalTransitionStyle.CoverVertical
            };
        }
    }
    return base.Show(request);
}

我需要这个的原因是因为当我关闭需要它的视图控制器的特殊流程时没有这个功能,它不会关闭该流程中的所有视图控制器,它一次只关闭其中一个

Image to supplement the question

解决方法

如果你想在一个 Modal ViewController 中导航,你通常会用 MvvmCross 做的是首先向模态添加一个 MvxModalPresentationAttribute,它将承载导航的其余部分,你将 WrapInNavigationController 设置为 {{ 1}}。

对于孩子来说,这只是常规的子导航,不需要任何属性。

如果您想控制模态的弹出方式,您可以创建自己的 true 并使用 MvxPresentationHint 在演示者中注册。

然后,您将在 ViewModel 中更改演示文稿调用 AddPresentationHintHandler

至于演示提示,它可能应该只调用 NavigationService.ChangePresentation(your hint),这可能会满足您的需求。

,

TLDR:感受那些会跟随你并以正确方式构建东西的开发人员

所以我深入研究了 MvvmCross MvxIosViewPresenter source code 并能够使用这个新的覆盖 CreateOverridePresentationAttributeViewInstance()

我需要请求对象来查看表示值,因此我更新了 Show 函数,该函数在其他覆盖之前被调用,如下所示:

MvxViewModelRequest _request;
public override Task<bool> Show(MvxViewModelRequest request)
{
    _request = request;
    return base.Show(request);
}

而且我能够通过这种方式获得 ViewController,以便有选择地将其呈现为模态:

{
    var view = base.CreateOverridePresentationAttributeViewInstance(viewType);
    if (_request.PresentationValues.ContainsKey("NavigationMode") &&
_request.PresentationValues["NavigationMode"] == "WrapInModalWithNavController")
    {
        var vc = view as IModalPresentation;

        vc.ModalPresentationAttribute = new MvxModalPresentationAttribute
        {
            WrapInNavigationController = true,ModalPresentationStyle = UIModalPresentationStyle.OverFullScreen,ModalTransitionStyle = UIModalTransitionStyle.CoverVertical
        };
        return vc;
    }                    
    return view;
}

然后关闭模态是另一个挑战,我能够使用 TryCloseViewControllerInsideStackChangePresentation 覆盖来弄清楚