试图通过微软的例子来理解MVVM

时间:2016-04-01 04:28:43

标签: c# windows-phone-8 mvvm

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

看起来ViewModel包含一组模型,它们被设置为视图的datacontext。

在MVVM中,ViewModel不应该是视图的datacontext,Model会修改ViewModel,然后会影响View吗?

2 个答案:

答案 0 :(得分:5)

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

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

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

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

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

通常,您会将视图的DataContext绑定到viewmodel。

其他问题

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

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

vm.GetAccomplishments();

...由于它是void,因此不会“获取”任何内容。如果您的订单错误,该方法会填充您必须阅读的Accomplishments属性,这太糟糕了。

答案 1 :(得分: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;
    }
  }
}

在上面的课程中,您现在可以对&#34; CanLogin &#34;进行数据绑定。属于您的&#34;已启用&#34;视图中的属性,以便只有在用户名和密码具有值时才能按下按钮,即使&#34; CanLogin&#34;不属于模型的一部分。

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

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