模板形式的MVVM模式

时间:2011-07-30 14:33:40

标签: silverlight templates mvvm childwindow

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

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

  1. 对于必须在弹出窗口中显示的“必需”视图,viewModel需要创建一个ChildWindow实例,向其添加“required”视图,然后显示Childwindow。还处理关闭/关闭事件。
  2. 我确信我的方法存在缺陷,但我无法找到一种方法将UI逻辑与业务逻辑完全分开。有人可以提供更好的方法。

    感谢。 甲

3 个答案:

答案 0 :(得分:3)

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

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

正如您所发现的那样,使用虚拟机的问题是,最终您遇到了需要了解视图的情况(这是他们永远不知道的一件事)。

我们遵循的基本规则是:

  • 控制人员根据事件做出决定
  • 控制器获取数据并将其放入适当的视图模型属性
  • 控制器将View Models的ICommand属性设置为拦截事件
  • 控制器会显示视图(如果未在其他地方暗示)
  • 查看模型是“愚蠢的”。绑定的保留数据和 nothing else
  • 视图知道它们显示某种形状的数据,但不知道它来自何处

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

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

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

这是我想到的解决方案。

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

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

    • 查看姓名
    • ViewModel实例。
  2. 在窗体ViewModel上,它负责将所有视图聚合在一起,并根据具体情况调出子窗口。添加三个属性

    • 列出FormViews
    • 列出ChildWindowViews。
    • 动作ShowChildWindow
  3. FormView模型将实例化所需的视图模型,从其MEF元标记中收集每个视图模型的视图名称,并填充FormView和ChildWindowView属性。完成Form ViewModel处理请求并填充了两个属性后,如果ChildWindow不为空,它将使用true参数触发ShowWindow委托。

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

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

      • 当引发ShowChildWindow操作时,它创建的Form View中的代码隐藏最少,并显示绑定到ChildWindowViews属性的ChildWindow。 ChildWindow属性使用相同的IValueCOnverter来创建所请求视图的实例。

    2. 听起来怎么样?请评论

      enter code here