如何使用 MVVMCross 构建视图模型

Posted

技术标签:

【中文标题】如何使用 MVVMCross 构建视图模型【英文标题】:How to structure viewmodels with MVVMCross 【发布时间】:2013-01-14 00:20:57 【问题描述】:

我正在迈出 MvvmCross 框架的第一步,我正在尝试确定项目和类结构方面的最佳方法。 我现在最关心的是决定如何组织我的视图模型,以便在它们之间共享数据,同时遵循 mvvm 指导。

我有一个关于视图和相应视图模型(主要和配置)的简单示例。主视图有一些控件绑定到视图模型中的属性。配置视图允许用户更改文本颜色、列表中的项目数量等...当用户更改配置时,这应该反映在主视图中。

我的第一个方法是创建单独的视图和视图模型。但是如何通知主视图配置已更改? 我在Github/Slodge 下看到了 Sphero 项目,我意识到视图模型可以直接引用其他视图。这样,每次配置更改时通知主视图相当容易。但这不是 mvvm 推荐的解耦视图模型的偏差吗?

我能否就处理这种类结构的最佳方法获得一些见解?

【问题讨论】:

【参考方案1】:

处理这种类结构的最佳方法

在我看来,“最佳方式”最重要的衡量标准是选择一种意味着您的应用可以运行的方式。


您看过的示例 - sphero 球控制 - 有两个独立视图模型(home、gangnam、about、sphero 等)的示例,并且它有一些相互了解的视图模型的示例 -球体视图模型及其子视图模型。

在这种特殊情况下,这些视图模型都相互了解的原因是因为它们都是单个显示的一部分 - 它们被设计为一起位于单个网格、枢轴或选项卡式 UI 中。为了帮助他们合作,我通过 IParent 和 IChild 接口为他们提供了相互引用。

这不是 mvvm 推荐的解耦视图模型的偏差吗?

我承认这确实意味着设计不是完全解耦的,如果我将来需要移动或重用这些子虚拟机,那么我可能需要进行一些代码重构 - 但现在设计工作对我来说很好,如果我需要,我个人很高兴在未来进行重构。


我现在最关心的是决定如何组织我的视图模型以便在它们之间共享数据并同时遵循 mvvm 指导

如果您正在构建复合(选项卡式)视图并且您不喜欢使用聚合视图模型(例如 sphero vm 及其子视图),那么请不要这样做。

我确信在 sphero 中使用一个大视图模型、使用通过信使通信的多个视图模型或使用通过一个或多个自定义服务进行通信的多个视图模型都可以实现相同的效果。

对于您给出的特定示例 - 配置和主视图,我认为这不适合选项卡式场景 - 我可能会使用信使对此进行编码 - 这将为我提供灵活的广播和接收机制更改应用各个部分的通知。

但是,其他设计绝对是可用且可行的 - 例如,您可以轻松地让视图模型在每次显示时刷新其配置(这样做需要挂钩到视图中的 onnavigatedto、viewwillapear 和 on resume 调用)。


总结:

我同意您编写独立视图模型并让它们通过服务进行通信的总体目标。 在主页和设置页面的情况下,我可能会使用 2 个单独的虚拟机和一个信使 在选项卡式/透视 UI 的情况下,我个人已经脱离了这种完美的范式 - 但在 mvx 中没有任何东西可以强迫您关注我

【讨论】:

感谢您的回答。我想这真的是一个人要完成工作的纯粹程度和工作量的问题......我认为***(和其他人)现在将成为我最好的新朋友:) 只是不要假设你知道谁是纯粹主义者......例如阅读肯特贝克的回答和***.com/questions/153234/how-deep-are-your-unit-tests的第一条评论【参考方案2】:

在我使用 MvvmCross 构建的项目中,我决定使用视图模型来表示视图(屏幕)及其状态。我的视图模型使用 ISQLiteConnectionFactory 连接到 SQLite 数据库。我使用存储在 SQLite 数据库中的模型来表示项目中事物的状态。我的视图模型从 SQLite 数据库中获取模型,分析它们并做出反应。

示例。我有一个屏幕,用户可以在其中标记他/她想要在设备上下载一段数据。我的模型有一个标志是应该下载还是已经下载了那条数据。当我打开另一个负责下载数据的屏幕时,它会查看 SQLite 是否有任何模型标记为下载并对其做出反应。

这就是我决定在视图模型之间共享数据的方式。优点是数据始终保存在数据库中,强制关闭应用不会导致数据丢失(或未按预期发生)。

【讨论】:

谢谢你的例子。这是/是我最初的方法。拥有一个可以保存信息并且可用于所有视图模型的服务。我目前正在采用一种“混合”方法,类似于 Stuart 在 Sphero 项目中使用的方法。在某些情况下,我会直接在其他 ViewModel 中引用 ViewModel。我只是尽量不要过度使用这种方法,只是为了 ViewModel 解耦:)

以上是关于如何使用 MVVMCross 构建视图模型的主要内容,如果未能解决你的问题,请参考以下文章

使用 mvvmcross,我如何“共享”一个视图模型以使用 iphone 的视图和 ipad 的另一个视图?有啥特殊的命名约定吗?

MvvMCross 导航回多个视图模型/截断导航堆栈

如何通过 Xamarin MvvmCross 中的 BottomNavigationView 在视图模型之间导航

MvvmCross 4 和 Xamarin.iOS -> 使用 Storyboard 时如何从 Core 加载视图控制器?

使用 mvvmcross 显示视图模型时无法解析当前的***活动

Mvvmcross - 从常规活动中显示 mvvmcross 视图模型