MVVM和存储库问题

Bil*_*llG 5 mvvm

假设我的应用程序中有两个视图,即MemberListView和MemberEditView.它们与透视viewModels,MemberListViewModel和MemberEditViewModel相关联.模型与存储库类MemberRepository对话,该类具有成员类的CRUD方法.

在MemberEditView表单中,我有几个下拉列表显示类似Status(Active/Inactive/Pending),成员交易代码等.它们是我的viewModel中的ObservableCollection对象,并绑定到视图上的ComboBoxes.MemberRepository是否应该处理用于检索每个要显示的列表的gets?

如果在MemberEditView上我有一个网格,显示该成员多年来所有的工作.如果用户双击其中一个作业,则会调用JobHistoryEditView以显示作业信息,并且它具有JobHistoryViewModel.MemberRepository应该处理JobHistory CRUD方法还是应该有一个单独的JobHistory存储库?

Sco*_*ock 2

大多数 MVVM 应用程序都具有以下架构:

View -> ViewModel -> Model -> Repository
Run Code Online (Sandbox Code Playgroud)

我最近一直在支持一种变体:

View -> ViewModel <- Presenter -> Model -> Repository
Run Code Online (Sandbox Code Playgroud)

(其中 A -> B 表示“A 知道 B”,但 B 不知道 A。)

请注意,在这两种情况下,唯一了解存储库的是模型,而不是视图模型。您的模型不仅仅是领域实体,它还必须容纳业务逻辑。显然,您的业务逻辑必须支持的用户故事之一是我所说的MemberEditTask

public class MemberEditTask
{
    private readonly Member _member;

    public MemberEditTask(Member member, IRepository repository)
    {
        this._member = member;
        this.StatusChoices = repository.GetPossibleMemberStatuses(member);
    }

    public ReadOnlyCollection<MemberStatus> StatusChoices { get; private set; }

    public MemberStatus Status
    {
        get { return this._member.Status; }
        set
        {
            if(!this.StatusChoices.Contains(value)) 
            { 
                throw new ArgumentOutOfRangeException();
            }
            this._member.Status = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所有这些逻辑都属于您的模型,因为可能的选择列表(并验证其中之一已被实际选择)是由业务逻辑定义的。您还可以想象其他一些消耗 的东西MemberEditTask,例如在服务器上运行的自动进程,它编辑成员以响应上传到 FTP 服务器上的文件,或者后台进程(在一定时间后将状态设置为“非活动”) 。所有这些事情都需要执行相同的业务规则,因此它们都必须是通用的(而不是在 ViewModel 中)。

因此,给定该类,ViewModel 类如下所示:

public class MemberEditViewModel : ViewModelBase
{
    private readonly MemberEditTask _task;

    public MemberEditViewModel(MemberEditTask task)
    {
        this._task = task;
    }

    public IEnumerable<MemberStatus> StatusChoices 
        { get { return this._task.StatusChoices; }

    public MemberStatus Status 
    {
        get { return this._task.Status; }
        set
        {
            this._task.Status = value;
            NotifyAllPropertiesChanged();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,为了非常简单的方便,只需相信这NotifyAllPropertiesChanged是一个受保护的方法,它使用反射在ViewModel 的所有ViewModelBase公共属性上引发事件。:) 这当然有点矫枉过正,但它在更重要的一点上发挥作用......PropertyChanged

这几乎是一个愚蠢的例子,因为在这种情况下,MemberEditViewModel这是不必要的。如果视图是唯一的一个设置Status,那么实际上也没有必要引发属性更改事件!当然在现实世界中,你会有更多的属性,并且会有交互。ViewModel 存在的原因是在其视图相关属性发生更改时通知消费者,而这是 Model 不会做的事情(在我看来也不应该这样做)。(ViewModel 还具有额外的特定于视图的逻辑来支持动画等)

所以回到你的问题...从 ViewModel 的角度来看,MemberRepository 是否负责执行状态的获取是无关紧要的,因为存储库是模型使用的服务。Model 是 ViewModel 使用的服务。使任务/工作流/流程/任何内容的模型公开状态选项列表。

抱歉,如果这很啰嗦。