视图模型应该是特定功能区域的用户交互模型
例如,如果您有一个项目列表页面,并且用户可以执行某些操作,例如删除项目、编辑项目、打印有关项目 那么您应该设计一个包含与此接口相关的数据和操作的视图模型:
例如视图模型应包含:
* A bindable container for the project data (list of projects)
* Actions that handle edit/delete interaction
* An action to handle the print functionality
这些操作中的实际功能可能不包含在视图模型中(VM 可能已经收到注入的服务,例如打印服务或项目存储库),但执行这些操作的责任在于 VM。
可能还需要将每个数据项(项目)包装在视图模型中,以便可以添加其他与交互相关的属性/操作 - 例如“选定”属性(假设用户想要多选视图中的项目 - 您可以向 ProjectViewModel 添加一个选定的属性,该属性将包装每个项目,这使得绑定变得容易)
您最终可能会得到以下结果:
public class ProjectOverviewViewModel
{
public IList<ProjectViewModel> Projects { get;set; }
public ProjectViewModel SelectedProject { get;set;}
public void EditSelected()
{
// Code to open edit page for the selected project
}
public void Print()
{
}
}
以及带有可选属性的ProjectViewModel
public class ProjectViewModel
{
// Either put the actual data item in here and wrap it:
public Project Project {get;set;}
// Or copy properties onto the viewmodel using automapper or some other mapping framework...
// or manually :(
// e.g. properties mirrored from the entity object:
public int ProjectId { get;set;}
public string ProjectName { get;set;}
// The selected property - now your 'Selected' logic is a function of the view/viewmodel
// not the entity. The entity should only be concerned with data persistence
public bool IsSelected {get;set;}
}
您可能还希望将视图模型组合在一起以构建更复杂的视图。假设您有一个项目页面和一个“参与项目的用户”页面,并且您想要另一个并排显示的页面(并允许您单击将刷新用户窗格的项目) - 这可以通过合成视图模型(通过创建另一个视图模型,其中包含两个视图模型作为属性并连接两者之间的交互)
public class ProjectAndUserOverView
{
public ProjectOverviewViewModel ProjectOverview {get;set;}
public ProjectUsersViewModel ProjectUsers {get;set;}
// Code here to listen for property changes in ProjectOverview and if SelectedProject changes
// call ProjectUsersViewModel to refresh the data for the selected user
}
最终你只是对用户交互进行建模,你可以做得越模块化,就越容易编写更简洁、更可维护的代码
有一些很好的 MVVM 框架 - 我个人最喜欢的是 Caliburn Micro,因为它使上述工作变得非常简单(默认情况下它大量使用约定)并且很容易进入。