基于MvvmCross动态加载绑定ViewModel的UIViewController
嘿,我之前在MvvmCross 5.x版本里也处理过类似的非标准导航场景,Segues确实和MvvmCross的默认绑定逻辑不太兼容,不过手动实例化并绑定ViewModel的方法其实挺清晰的,给你两个实用的方案:
方案1:手动实例化并绑定(最适合你的非导航场景)
这个方法完全脱离MvvmCross的导航栈,适合你需要动态创建控制器但不需要加入导航层级的情况:
确保控制器继承正确的基类
- 如果你用XIB创建控制器:让它继承
MvxViewController - 如果你用Storyboard创建控制器:让它继承
MvxStoryboardViewController<YourViewModelType>
- 如果你用XIB创建控制器:让它继承
获取ViewModel实例
通过MvvmCross的依赖注入容器获取你的ViewModel:var viewModel = Mvx.IoCProvider.Resolve<YourTargetViewModel>(); // 如果需要给ViewModel传参,可以在Resolve后手动赋值,或者用构造函数注入(推荐)实例化ViewController并绑定ViewModel
- 对于XIB场景:
// 假设你的XIB文件名和控制器类名一致 var viewController = new YourViewController(viewModel); // 如果XIB文件名不同,需要指定XIB名称: // var viewController = new YourViewController(viewModel, "CustomXibName"); - 对于Storyboard场景:
var storyboard = UIStoryboard.FromName("YourStoryboardFileName", null); var viewController = storyboard.InstantiateViewController(nameof(YourViewController)) as MvxStoryboardViewController<YourTargetViewModel>; // 手动绑定ViewModel viewController.ViewModel = viewModel;
- 对于XIB场景:
触发绑定初始化
大部分情况下,MvvmCross的基类会在ViewModel属性设置后自动初始化绑定,但如果遇到绑定不生效的情况,可以手动调用:viewController.InitializeViewModelBinding();
方案2:利用MvvmCross导航服务(适合允许入栈的场景)
如果你的场景允许把控制器加入导航栈,也可以直接调用MvvmCross的导航服务来完成实例化和绑定:
var viewModel = Mvx.IoCProvider.Resolve<YourTargetViewModel>(); // 如果需要传参,可以用Navigate的重载: // await Mvx.IoCProvider.Resolve<IMvxNavigationService>().Navigate<YourTargetViewModel, YourParameterType>(parameter); await Mvx.IoCProvider.Resolve<IMvxNavigationService>().Navigate(viewModel);
这个方法会自动处理ViewModel和ViewController的绑定,以及导航栈的管理,但如果你的控制器不需要入栈,方案1更合适。
关键注意事项
- 你的ViewModel必须继承
MvxViewModel,否则MvvmCross无法识别和处理绑定 - 对于Storyboard中的控制器,一定要在Storyboard编辑器里把控制器的Class属性设置为你的自定义控制器类名,否则无法正确实例化
- 在MvvmCross 5.0.6中,依赖注入容器的访问方式是
Mvx.IoCProvider,如果你之前用的是旧版的Mvx.Resolve,记得替换成这个 - 尽量在ViewController的
View加载之前设置ViewModel属性,这样绑定逻辑能在ViewDidLoad阶段正常触发
内容的提问来源于stack exchange,提问作者Stephan
相关产品推荐
相关产品推荐

