【发布时间】:2016-04-01 04:28:43
【问题描述】:
看起来 ViewModel 包含一组模型,这些模型设置为视图的数据上下文。
在 MVVM 中,视图模型不应该是视图的数据上下文,模型将在其中修改视图模型,然后影响视图吗?
【问题讨论】:
标签: c# windows-phone-8 mvvm
看起来 ViewModel 包含一组模型,这些模型设置为视图的数据上下文。
在 MVVM 中,视图模型不应该是视图的数据上下文,模型将在其中修改视图模型,然后影响视图吗?
【问题讨论】:
标签: c# windows-phone-8 mvvm
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 属性,如果您弄错了顺序,无论如何您都必须阅读该属性太糟糕了。
【讨论】:
如果您关注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。
【讨论】: