MVVM和存储库问题

时间:2010-12-08 20:05:11

标签: mvvm

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

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

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

1 个答案:

答案 0 :(得分:2)

大多数MVVM应用程序都具有这种架构:

View -> ViewModel -> Model -> Repository

我最近一直支持变种:

View -> ViewModel <- Presenter -> Model -> Repository

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

请注意,在这两种情况下,唯一了解存储库的是Model,而不是ViewModel。您的模型不仅仅是域实体,还必须包含业务逻辑。显然,您的业务逻辑必须支持的用户故事之一是我称之为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;
        }
    }
}

所有这些逻辑都属于您的模型,因为业务逻辑定义了可能的选择列表(并验证其中一个实际被选中)。您还可以想象使用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();
        }
    }
}

在这种情况下,作为一个非常简单的方便,只需认为NotifyAllPropertiesChangedViewModelBase的受保护方法,它使用反射在所有PropertyChanged事件 ViewModel的公共属性。 :)当然这太过分了,但它更重要的一点......

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

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

对不起,如果这是啰嗦。