【问题标题】:Trying to understand MVVM through microsoft example试图通过微软的例子来理解 MVVM
【发布时间】:2016-04-01 04:28:43
【问题描述】:

看这个例子:https://msdn.microsoft.com/en-us/library/windows/apps/gg521153%28v=vs.105%29.aspx?f=255&MSPPError=-2147217396

看起来 ViewModel 包含一组模型,这些模型设置为视图的数据上下文。

在 MVVM 中,视图模型不应该是视图的数据上下文,模型将在其中修改视图模型,然后影响视图吗?

【问题讨论】:

    标签: c# windows-phone-8 mvvm


    【解决方案1】:

    TL; DR - 这个例子根本不是 MVVM。

    是的,这是一个糟糕的 MVVM 示例。视图在运行时绑定到查询“视图模型”中的属性的 LINQ 结果,而不是绑定到视图模型本身。 Accomplishments 不在其他任何地方使用。

    换句话说,在 OP 所指向的示例中,视图根本没有绑定到视图模型,而是不正确地直接绑定到模型集合。 我不相信 ObservableCollection<> 构成合理的 ViewModel。 (或IEnumerable<>IList<> 或类似名称)

    这是视图代码隐藏中的违规行:

    LevelViewOnPage.DataContext = from Accomplishment in vm.Accomplishments 
                                  where Accomplishment.Type == "Level" 
                                  select Accomplishment;
    

    通常您会将视图的DataContext 绑定到视图模型。

    其他问题

    代码审查方面,它实际上非常可怕,有一些奇怪的设计和命名约定。

    视图通过以下方式调用视图模型:

    vm.GetAccomplishments();
    

    ...它不会“得到”任何东西,因为它是void。该方法填充了Accomplishments 属性,如果您弄错了顺序,无论如何您都必须阅读该属性太糟糕了。

    【讨论】:

    • "通常你会将视图的 DataContext 绑定到视图模型。"是的,该示例甚至没有对页面和“视图模型”执行此操作。 VM 似乎作为代码隐藏中的一个字段单独存在。
    • @BoltClock 同意。似乎 MS 写这段代码的人都不知道
    • 是的,这一切都说得通,我也对 GetAccomplishments 函数持怀疑态度,但我认为因为微软将它用作 MVVM 的示例,所以它不可能是坏代码......
    【解决方案2】:

    如果您关注SOLID principles of object oriented programming,那将为 ViewModel 提供不止一个更改理由。模型就是这样 - 一个模型,一个零智能的愚蠢对象。

    ViewModel 的职责只是保持可视化状态,例如显示 Person 的当前值,并将任何更改传递给适当的底层服务类。

    无论如何,ViewModel 是动作发生的地方。

    Order/OrderLines 的永无止境的示例在其中构造了一个包含您想要显示的所有属性的 ViewModel,这进一步表明 ViewModel 是关于编排要在视图中显示的对象并促进与其他对象的通信你的代码

    ViewModel 通常还扩展视图的属性,例如,您可以在 LoginViewModel 中拥有如下所示的属性:

    public class LoginViewModel : INotifyPropertyChanged
    {
      public string Username{get;set;}
      public string Password{get;set;}
    
      public bool CanLogin {
        get{
            return Username.Length > 0 && Password.Length > 0;
        }
      }
    }
    

    在上面的类中,您现在可以将“CanLogin”属性数据绑定到视图中的“Enabled”属性,这样只有在用户名和密码有值时才能按下按钮,即使虽然“CanLogin”不是模型的一部分。

    然而,最大的争论是 ViewModel 是否已经有太多的责任,因为它既提供对模型所有属性的访问(责任 1),又促进一些代码逻辑(即调用“UpdatePerson”来自某个 PersonService 类),这违反了单一责任原则。

    出于这个原因,并且为了更清晰地分离关注点,我经常创建两个不同级别的 ViewModel - 级别 1 是到模型的纯映射,它基本上只是为我的模型提供了所有模型公共属性上的 INotifyPropertyChanged ,在第二级中,我创建了与底层服务类(例如“VerifyPassword()”、“UpdatePerson()”等)进行交互的 ViewModel。

    【讨论】:

    • 虽然关于 ViewModel 和 SOLID 的回答很好,但 OP 表达的问题是示例中的视图根本没有绑定到视图模型。
    • MVVM 中的模型通常是一个层,而不是单个类(实体)。模式通常是指业务逻辑和数据访问
    猜你喜欢
    • 2011-06-17
    • 2012-11-28
    • 2016-05-17
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多