3

在我的 silverlight 应用程序中,用户可以创建多个表单模板。根据选择的模板,表单将以特定顺序显示一组视图。此外,如果模板上存在某些视图,则它们是“必需的”。客户希望这些视图显示在弹出表单中,以便用户首先关注那些“必需的”视图,然后再转到表单上的其他视图。

现在,我看到自己为了这个要求打破了 MVVM 模式。这就是为什么... 1. ViewModel 可以从数据库中读取模板,获取视图(使用 MEF)但是要将它们添加到表单中,它需要知道布局网格的名称并将视图作为子视图添加到那个网格。这就像告诉 ViewModel 关于违反 MVVM 设计模式的 UI 元素一样。

  1. 对于必须在弹出窗口中显示的“必需”视图,viewModel 需要创建一个 ChildWindow 实例,将“必需”视图添加到其中,然后显示 ChildWindow。还处理关闭/关闭事件。

我确信我的方法有缺陷,但无法找到一种方法将 UI 逻辑与此处的业务逻辑完全分开。有人可以提供更好的方法。

谢谢。一种

4

3 回答 3

3

恕我直言:这是另一种情况,只需将控制器添加到 MVVM 即可干净地解决所有问题。我们称之为 MVCVM(不等于有效罗马数字的耻辱):)

我们在所有最近的项目中成功使用的模式是在模块中注册控制器,并在启动时初始化它们。控制器非常轻巧/纤薄,是应用程序在监听或发送消息的整个生命周期中唯一需要保留的东西。然后在他们的初始化方法中注册他们需要拥有的任何东西(视图和视图模型等)。这种轻量级的仅内存逻辑模式也使应用程序更轻薄(例如,对于 WP7 更好)。

正如您所发现的,仅使用 VM 的问题在于,最终您会遇到他们需要了解视图的情况(这是他们永远不应该知道的一件事)。

我们遵循的基本规则是:

  • 控制器根据事件做出决策
  • 控制器获取数据并将其放置在适当的视图模型属性中
  • Controllers 设置 View Models 的 ICommand 属性来拦截事件
  • 控制器使视图出现(如果在其他地方没有暗示)
  • 视图模型是“愚蠢的”。用于绑定的保留数据,仅此而已
  • 视图知道它们显示某种形状的数据,但不知道它来自哪里

最后两点是你永远不应该打破的,否则关注点分离就会消失。

到目前为止,您需要让您的虚拟机直接访问数据库(糟糕),您的虚拟机获得视图(非常糟糕)并且需要您的虚拟机弹出另一个窗口(非常糟糕)。

考虑一下。您可能会开始(重新)将控制器引入您的 MVVM 应用程序。如果您想了解更多信息,请询问。

于 2011-07-30T16:41:43.783 回答
0

在我们的项目中,当需要完成 UI 特定的事情时,需要在视图和视图模型之间进行通信时,我们一直遵循事件订阅机制。解决问题的一种方法是在视图模型上发布一个事件,并将视图列表作为事件参数。或者可能存在维护此列表的属性,在视图模型上设置,并且在更新属性时触发事件。在视图中,您可以订阅事件并将控件添加到布局根。这是可测试的解决方案,不会在视图模型中放置任何特定于视图的内容。

如果您有使用 MVVM 框架的自由,那么您可以尝试 PRISM 或 MVVMLight 之类的东西。Prism 提供事件同意器,而 MVVMLight 提供 Messenger 类,可以解耦视图和视图模型以及不同视图模型之间的通信。

于 2011-07-31T01:04:42.647 回答
0

这是我想到的解决方案。

1. 使用带有与 ViewModel 关联的 View 名称的元标记装饰 ViewModel。

  1. 创建一个名为 ViewViewModel 的新类,其中包含两个属性

    • 查看名称
    • ViewModel 实例。
  2. 在 Form ViewModel 上,它负责将所有 View 聚合在一起,并根据情况打开一个子窗口。添加三个属性

    • 列出表单视图
    • 列出 ChildWindowViews。
    • 动作 ShowChildWindow

FormView 模型将实例化所需的视图模型,从每个视图模型的 MEF 元标记中收集视图名称,并填充 FormView 和 ChildWindowView 属性。一旦 Form ViewModel 处理完请求并填充了两个属性,如果 ChildWindow 不为空,它会使用 true 参数触发 ShowWindow 委托。

  1. 表单视图将执行以下操作

    • 布局根将有一个绑定到 FormView 属性的堆栈面板。将有一个 IValueConverter 处理 FormViews 列表中的每个条目。对于每个 ViewName,它会查找并创建视图的实例。将 DataContext 设置为 ViewModel。

    • 当引发 ShowChildWindow 操作时,窗体视图中有最小的代码隐藏,它创建并显示一个绑定到 ChildWindowViews 属性的 ChildWindow。ChildWindow 属性使用相同的 IValueCONverter 来创建请求视图的实例。

听起来怎么样?请评论

enter code here
于 2011-07-31T03:39:39.947 回答