【问题标题】:How should a ViewModel interact with a Repository?ViewModel 应该如何与 Repository 交互?
【发布时间】:2013-10-14 03:45:58
【问题描述】:

我正在学习使用 MVVM 构建应用程序,我有以下情况:

  • ViewModel 应显示Examination 类型的对象列表。此列表将被数据绑定到视图中的 ListView,从那里将被过滤,用户将选择 ActiveExamination 以供进一步使用。
  • “存在”在模型层中的存储库应该“表现为域对象的内存集合”,并在 ViewModel 中实例化。

现在我的问题是:存储库应该是数据绑定到视图的集合,还是应该只是实现 INPC 的属性的“数据源”?例如,从以下几种可能性中,是其中一个正确,另一个错误,还是两个都错误......?

// example where the list is replaced in order to be changed;

// ViewModel class (part of it)
public class ThisViewModel : ViewModelBase {
    public List<Examination> ExaminationList {
        get { return _examinationList; }
        set { _examinationList = value;
              NotifyOfPropertyChange("ExaminationList"); }
    }
}


var repo = new ExaminationRepository();
ThisViewModel.ExaminationList = repo.getAll().where(ex => ex.Value > 20).ToList();

第二个选项

// Example where the very property IS a repository

// ViewModel class (part of it)
public class ThisViewModel : ViewModelBase {

    // the List is actually a repository in disguise.
    IEnumerable _examinationList = new ExaminationRepository();

    public List<Examination> ExaminationList {
        get { return _examinationList; }
        set { _examinationList = value;
              // This should be "NotifyOfCollectionChange", I guess...
              NotifyOfPropertyChange("ExaminationList"); }
    }
}

很可能我在这里很困惑/误会了,但是我的应用程序在架构方面相当小且简单,而且我真的不打算使用我见过的与此类问题相关的大多数框架和高级概念(ORM , IoC, DI),而我主要关心的是“如何在 WPF/MVVM 数据绑定环境中正确处理可变的、基于存储库的集合”。

编辑:关于我的应用程序的一些上下文: 该应用程序是执行临床检查的应用程序。它有一个患者列表,每个患者都有自己的检查。有一个患者存储库和一个检查存储库。当我在 PatientList 中选择一位患者时,该患者的 ExamsList 会显示来自考试 repo 的匹配考试。用户对患者和检查的操作是 CRUD,或者更具体地说是 BREAD(浏览、阅读、编辑、添加和删除)。

感谢您的建议!

【问题讨论】:

  • "如何在 WPF/MVVM 数据绑定环境中正确处理一个可变的、基于存储库的集合" --- 为什么你希望它是可变的?你不希望它是不可变的吗?这取决于您希望如何使用 ExamList 的情况,它是否只会显示数据库中的数据而用户无法将项目添加回数据库?
  • @LeoLorenzoLuis 我用更多的上下文编辑了这个问题。
  • 然后我要做的是创建一个 ObservableCollection 属性并延迟加载支持属性以获取数据库中的项目,并且集合中的任何后续项目都将在添加/时得到正确处理编辑/删除。您的层分离很好,您只需在 ViewModel 中正确使用它。我不同意 Sheridan 的回答,即您应该始终在 UI 中填充/显示单独的集合。不不不。
  • @LeoLorenzoLuis 非常感谢。还有一个疑问:您提到“延迟加载 becking 属性”和“任何后续项目都将得到妥善处理”。它是在ObservableCollection&lt;T&gt; 本身的帮助下实现的,还是我应该覆盖或实现代码,或者我应该将代码放在 setter/getter 中......?有点迷茫,还是……
  • 不是你自己实现的类实现的。就像这样 public ObservableCollection Patients { get { if(_patients == null) { _patients == //在这里调用仓库 } return _patients;然后在代码的其他部分,您只需调用 Patient.Add 或其他东西或 Remove,这些都是内置在类中的。

标签: wpf data-binding mvvm repository-pattern observablecollection


【解决方案1】:

在我看来,为了在大型应用程序中实现最佳分离,您应该始终使用单独的集合从数据库中填充,然后在 UI 中显示。这确实意味着您必须遍历该集合两次,但这在 WPF 中通常是必需的,因为我们喜欢为 UI 添加额外的显示属性,例如 IsSelectedIsFocused(如果我们正在填充视图模型对象)。

这样做的主要原因是允许我们在应用程序中连接各个层,以便我们可以独立测试每个层。如果您没有要求这样做,那么也许它并不那么重要。

我一直想知道为什么微软在其自动生成的类(例如来自 Linq2SQL)中实现 INotifyPropertyChangedINotifyPropertyChanging 接口,而在 UI 中使用这些类直接破坏了他们自己总是告诉的层之间的分离开发人员要遵守。

更新>>>

我会说,对于一个小型应用程序,您如何以及在何处执行这些操作并不重要。有时在编写一个非常小的应用程序时,我什至不费心使用 MVVM。创建层和/或实现 MVVM 文件夹结构都会增加额外的开发时间和额外的代码,我觉得它们只有在 你时才有用;

a) 将分别测试应用程序的各个层,或

b) 可能在未来的某个阶段需要“交换”一个或多个层,例如。例如,从 SQL 数据库移动到 Oracle 数据库,或者从 WPF UI 移动到基于 Web 的 UI。

【讨论】:

  • 这是否意味着我的第一个代码块就足够了?我的应用程序相当小而简单,我不确定我是否完全理解您的考虑(我对数据绑定集合还没有太多经验)。
  • 是的,我会使用您的第一个示例。我经常将我的数据访问代码放入一个名为Refresh 的方法中,该方法在构造函数中调用,然后还给用户一个Command,他们可以使用它来调用此方法,例如。用户可以通过单击 UI 中的 Button 来刷新每个视图中的数据,该 UI 绑定到内部调用 Refresh 方法的 Command
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 2012-12-31
  • 2015-09-18
  • 2011-09-16
相关资源
最近更新 更多