【问题标题】:One Model Entity, Multiple Pages -> Multiple Views? Multiple ViewModels?一个模型实体,多个页面 -> 多个视图?多个视图模型?
【发布时间】:2011-02-22 01:06:16
【问题描述】:

由于屏幕空间有限,我将使用多个页面(连续显示 - 思考向导)捕获单个实体的用户输入。在我的模型中,我希望将此实体建模为单个类是正确的。

在 MVVM 实现中,我假设最好的 MVVM 实践将每个页面视为一个单独的视图。这是正确的吗?

对于每个 Page 是否有自己的 ViewModel 或者是否应该有一个 ViewModel 实例被多个 Pages 引用,是否就最佳 MVVM 实践达成了共识?

举例说明:

选项 1

Class A (X, Y, Z)
ViewModelA1 (X)
ViewModelA2 (Y)
ViewModelA3 (Z)
View1 captures ViewModelA1
View2 captures ViewModelA2
View3 captures ViewModelA3

选项 2

Class A (X, Y, Z)
ViewModelA (X, Y, Z)
View1 captures ViewModelA.X
View2 captures ViewModelA.Y
View3 captures ViewModelA.Z

【问题讨论】:

    标签: wpf silverlight mvvm windows-phone-7 mvvm-light


    【解决方案1】:

    “视图”一词说明了一切。这是数据的视图。 ViewModel 的工作是使来自模型的数据可呈现。需要对数据执行的任何操作都发生在视图模型中,以便视图可以显示它。

    通常,您的视图与视图模型之间存在一对一的关系,因为通常您只想以一种方式显示该数据。 (一个“视图”) 我偏离常规做法的地方(可能是 MVP 模式?)是,如果您想以多种不同的方式显示数据(例如,您想要条形图或折线图,或饼图)和数据所有视图都相同,那么您只需要一个视图模型。它是 DRY 原则的一个案例。如果您有三个视图模型并且它们都相同,则使用一个视图模型。多个视图。一个视图模型。

    【讨论】:

      【解决方案2】:

      我敢肯定,有些人会以一种或另一种方式强烈反对。从我的角度来看,这完全取决于您需要重用哪些代码。有以视图为中心和以模型为中心的方式来构建你的视图模型,我不认为任何一种方法总是正确的。

      如果您发现您的 ViewModel 倾向于在 UI 特定的逻辑上很重,一个好的设计将倾向于 View 和 ViewModel 之间的 1:1 关系,每个 ViewModel 包装多个模型。这种方法的危险在于,您可能会花费大量代码来连接每个 ViewModel 中的数据并使其保持同步,并且需要在每个 ViewModel 中重复这种连接。唉。

      但是,您也可能遇到一种情况(就像我在当前项目中所做的那样),ViewModel 必须处理底层模型中的复杂关系,并且可以从多个端点更新各种模型实体(即,用户或双工 WCF 服务)。在这种情况下,您会在每个 ViewModel 中花费大量时间来确保其数据与底层模型同步,并且在每个 ViewModel 中重新执行所有逻辑将是愚蠢的。在这种情况下,我发现最简洁的方法是让您的 ViewModel 与模型或多或少 1:1 映射,并在多个视图中重复使用。这种方法的缺点是您最终可能会将来自各种不同视图的大量特定于 UI 的代码混合到同一个类中,这会使测试和维护变得困难。 (是的,我知道 ViewModel 不应该与任何特定的 UI 紧密耦合,但你最终仍然会得到很多代码,实际上,“当用户执行绑定到我的某个 UI 元素的这个命令时”我假装什么都不知道,做其他我假装我不知道的事情会导致一个对话框被弹出。”即使在那个抽象级别,编码到 ViewModel 中的逻辑也可以从查看到查看。)

      还有各种混合方法,它们可能在实际场景中最有用。例如,您最终可能会在视图模型中使用继承层次结构,以便处理一个或多个基类中的通用连接,然后在继承链的更下游的类中添加特定于 UI 的部分。

      对于它的价值,我对大多数 MVVM 文章的不满之一是它们处理的场景过于简单,无法反映您在现实世界中发现的复杂性。一旦您通过 Customer -> Order -> OrderDetail 之类的表单,我发现我读过的大多数建议往往会崩溃,我只能自己寻找方式。

      【讨论】:

      • 我发现你的最后一段也一样,虽然有很多人在吹捧 MVVM 模式,但对于多个单一视图模型示例来说,它们都缺乏应用程序建模。
      • 有一些方法可以通过重构和部分类来分解复杂的视图模型。
      【解决方案3】:

      关于 MVVM 的相关最佳实践,我被教导(和实践):

      • 每个页面/视图都有一个 ViewModel。

      • ViewModel 应该只具有与使用它们的 View 相关的字段/属性。

      • 可以根据需要从多个底层逻辑模型/类组合 ViewModel。

      上述内容可能会产生更多模型,但随着时间的推移,它们会更容易使用,因为对单个视图/视图模型的更改不会影响其他视图或视图模型

      这符合您的第一个选项

      【讨论】:

        【解决方案4】:

        在 MVVM 实现中,我是 假设这是最好的 MVVM 实践 将每个页面视为一个单独的视图。 这是正确的吗?

        是的,我会这样做,具体取决于它的复杂程度。我认为大多数 WP7 应用程序的 MVVM 只是一种矫枉过正。

        【讨论】:

        • 感谢您的输入,我已将我主要感兴趣的问题加粗
        • 我不相信对此有太多共识,个人认为这可能取决于 lukas 建议的模型的复杂性。
        • 还要感谢 Nigel .. 到目前为止我看到的所有示例都表明 View 和 ViewModel 总是 1:1 ......这似乎是一个相当大的膨胀让我质疑这是公认的方法还是只是因为示例通常保持简单而被掩盖了。
        【解决方案5】:

        选项 1 是更好的模型。

        我不确定你所说的 X、Y 和 Z 是什么意思。

        您应该简单地将模型的相同实例传递给每个 ViewModel

        Class Model
        {
          string X { get;set;}
          string Y { get;set;}
          int Z { get;set;}
        }
        
        Class MainViewModel
        {
          // constructor
          ViewModel()
          {
            model = new Model()
            SubViewModel = new SubViewModel(model);
          }
        
          Model model {get;set;}
          SubViewModel sub { get;set;}
        
        }
        
        Class SubViewModel
        {
          // ctor
          SubViewModel(Model model)
          {
            this.model = model;
          }
        
          Model model { get;set;}
        }
        

        MainViewModel 处理每个 SubViewModel 之间的导航,但它们都在查看模型的同一个实例,因此它们都具有相同的数据。

        【讨论】:

        • 澄清一下,XYZ 是实体上的字段,这似乎是您在模型类示例中假设的内容。
        • 感谢您的意见。您认为 MainViewModel 是应用程序中所有数据的包含 ViewModel 吗?每个 SubViewModel 代表 ViewModelA1、A2、A3 以及在整个应用程序的不同视图中使用的任何其他 ViewModel。看起来您可能会建议 MainViewModel 仅用于将 VMA1、A2、A3 组合在一起,并且与应用程序中任何其他未提及的视图使用的其他 ViewModel 分开存在(抱歉,如果这令人困惑)。
        • 我很困惑的一件事,在你的例子中,我认为你没有将 SubViewModel 放在 ViewModelLocator 但 MainViewModel 是?
        • 我假设您正在谈论来自 MVVM-Light 的 ViewModelLocator,我认为这取决于您是否需要在其他地方使用 SubViewModel 或仅在一个视图中使用它。如果要求所有 VM 都通过 ViewModelLocator,那么它应该放在那里。否则,这将取决于具体情况。
        • 它只用于特定的视图。假设我有一个 MainView 和一个 MainViewModel。 MainViewModel 在 ViewModelLocator 中创建。在 MainViewModel 中说我有一个更复杂的部分,我想突破到它自己的视图 SubView。 SubView 有自己的 ViewModel,我应该在哪里创建 SubViewModel?它不需要在设计师的定位器中吗?这是一个类似的问题:stackoverflow.com/questions/4505919/…
        【解决方案6】:

        在某些任务上,我可能有多个模型与单个 ViewModel 相关联,并且该任务的多个视图。例如,使用分组、图像等创建产品。以产品为中心。

        我也有多个 ViewModel 由 Task 通过多个 View 驱动的任务。例如,在应用程序中创建一个用户帐户,其中包含多个第 3 方帐户(如 Facebook、Twitter 等)的混搭,其中每个第 3 方 API 都有自己的一组要求,但通过一系列步骤向用户显示为单个任务。专注于用户帐户。

        MVVM 模式根据需要灵活。定义任务,将其分解,然后确定最适合该任务的任务。

        【讨论】:

        • 感谢您的输入 - 听起来您是在说没有 MVVM 模式的定义以一种或另一种方式规定了这个细节。既然如此,我想这意味着它要么是你所描述的情景,要么是其中之一取决于你问的是谁。
        • 如果有一个关于如何使用 View ViewModel Model 完成 MVVM 的神奇公式,那么就会有关于它的书籍。答案是,关系如何在基本定义和指导方针之外发挥作用是特定于任务的。要记住的是,MVVM 只是一种指导模式,而不是一个固定的框架。所有的库都只是在模式之上添加了辅助例程,并且通过混合其他设计模式来增强 MVVM,它们都有非常不同的做事方式。
        【解决方案7】:

        看,你问的是这个:
        我有 1 M.
        我有 3 对。 (假设 最好创建 3 个 V)。

        我应该有 1 个虚拟机还是 3 个虚拟机?? 换句话说你问,VM 概念在哪一边更接近?在 M 侧还是 V 侧?

        根据我迄今为止对该模式的经验,VM 与 V 的关系MUCH 更密切。

        所以快速回答您的问题是:3 个虚拟机(选项 1)。选项 2 是思考这种模式的错误方式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多