初始化视图模型

nla*_*ker 10 mvvm silverlight-4.0

有些事情让我对MVVM感到困惑 - 如果我使用视图优先方法来构建我的对象(这似乎是最常见的方法,至少在经过多次阅读和搜索之后),我如何将上下文信息导入到视图模型中?

我已经看到许多类似问题的答案说"使用DI容器注入你的模型",但这对我没有帮助,所以我将提供一个小例子.

假设我的应用程序是PeopleEditor.它用于加载和编辑People对象,这些对象很复杂.当您加载应用程序时,您将获得一个主屏幕,将一堆人员加载到内存中 - 让我们说这些都可以通过我可以从我的容器中访问的集合进行访问.通过单击Person,您将进入编辑器屏幕.编辑器很复杂,因此这不是在一个屏幕上实现的简单的主 - 细节视图.

因此,在主屏幕上,当我单击一个人时,应用程序需要创建一个新视图和视图模型并显示视图.如果我首先通过容器创建viewmodel,我可以使用适当的person对象初始化它.这对我来说似乎很自然,所以我很难弄清楚为什么视图优先似乎是主要模式.我如何使用view-first方法执行此操作?该视图将创建viewmodel,它可以访问People的集合,但不知道它正在编辑哪个人.为清晰起见编辑:多人编辑可以同时存在,每个人编辑一个不同的人.

Prism 4.0 alpha的MVVM参考实现使用"状态处理程序",它基本上是应用程序用于在容器中存储构造函数参数的服务.它保存状态并调用ShowView,最终创建的viewmodel导入状态对象.这对我来说似乎很笨拙 - 就像它试图假装它松散耦合时,它真的不是.还有其他人有其他指导吗?

ktu*_*nik 3

恩拉沃克,

我不是专家,但我对视图优先和模型优先的了解是:

  1. View-First:视图程序ViewModel,您创建视图,然后自动创建视图模型。
  2. 模型优先:ViewModel 编程视图,您在根应用程序中创建 ViewModel 对象图,并将其分配给根视图数据上下文。然后让视图根据视图模型渲染其相关子视图。

并不是说模型优先方法不好,但是,我更喜欢视图优先方法,因为视图模型可以位于代码后面,因此当某些流程需要非绑定友好任务(PasswordBox、DialogConfirmation、ClosingForm 等)时,我可以写我的逻辑在代码后面。

不管怎样,为了解决这个问题,我通常使用 IOC 和事件聚合器的组合。这里是:

  1. 对于视图模型,需要上下文信息在 IOC 容器中注册其实例而不是其类型。所以它已经准备好了,即使它的观点还没有。
  2. 当发生导航操作(通过单击人员列表项)时,使用 IOC 容器解析器解析您的视图。并向导航总线发送带有指定参数的事件。此外,此事件将被目标 ViewModel 捕获并执行某些操作。

注册视图模型的实例并不是真正必要的。它只是为了确保当前一个视图模型调度事件时视图模型已准备好。

更新

但是为了用任何类型的本地上下文填充它,我需要使用全局工具向它发送事件?

在您的情况下,上下文对象不是本地的,而是对象调用之间传递的消息。显然,在模型优先方法中,您会执行以下操作:

//selectedPeople is contextual object
myPeopleDetailVM.LoadData(selectedPeople)
Run Code Online (Sandbox Code Playgroud)

selectedPeople当您传递给事件总线的参数时,它几乎是相同的。

如果您考虑性能,那么您可以将其与WPF 路由事件系统进行比较,在这种情况下,路由策略比事件总线更复杂,我认为如果您有足够的信心使用 WPF 路由事件,那么您应该使用事件聚合器。

如果您使用内置框架事件聚合器(prism、mvvmlight),我看到的唯一问题是,您的视图模型被事件总线污染,如果您抱怨这一点,那么我同意您的观点。

希望有帮助。