WPF/MVVM:在多控制器和关注点分离中重用ViewModel

WPF/MVVM:在多控制器和关注点分离中重用ViewModel,wpf,mvvm,viewmodel,reusability,Wpf,Mvvm,Viewmodel,Reusability,在myAdministration Controller中,我使用了一个PupilViewModel类似: _adminRepo.GetSchoolclassPupilList().ForEach(s => { SchoolclassViewModel sVM = new SchoolclassViewModel(s, _adminRepo); foreach (PupilViewModel pVM

在myAdministration Controller中,我使用了一个PupilViewModel类似:

_adminRepo.GetSchoolclassPupilList().ForEach(s =>
            {
                SchoolclassViewModel sVM = new SchoolclassViewModel(s, _adminRepo);

                foreach (PupilViewModel pVM in sVM.PupilListViewModel)
                {
                    pVM.Documents.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);
                    pVM.Documents.AddDocumentDelegate += new Action(OnAddDocument);
                    pVM.Documents.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);
                }
                SchoolclassList.Add(sVM);
            }); 
\u adminRepo.GetSchoolclassPupilList().ForEach(s=>
{
SchoolclassViewModel sVM=新的SchoolclassViewModel,_adminRepo;
foreach(sVM中的PupilViewModel pVM.PupilListViewModel)
{
pVM.Documents.DeleteDocumentDelegate+=新操作(OnDeleteDocument);
pVM.Documents.AddDocumentDelegate+=新操作(OnAddDocument);
pVM.Documents.OpenDocumentDelegate+=新操作(OnOpenDocument);
}
SchoolclassList.Add(sVM);
}); 
PupilViewModel是这样创建的:

public SchoolclassViewModel(Schoolclass schoolclass, IAdministrationRepository adminRepo)
        {
            _schoolclass = schoolclass;
            _adminRepo = adminRepo;  

            PupilListViewModel = new ObservableCollection<PupilViewModel>();
            schoolclass.Pupils.ForEach(p => PupilListViewModel.Add(new PupilViewModel(p, _adminRepo)));                      
        }
公共学校课堂视图模型(学校课堂、IAdministrationRepository adminRepo)
{
_班级=班级;
_adminRepo=adminRepo;
PupilListViewModel=新的ObservableCollection();
schoolclass.products.ForEach(p=>PupilListViewModel.Add(新的PupilViewModel(p,_adminRepo));
}
正如您肯定注意到的,PupilViewModel在其构造函数中采用了2个参数。 重要的一个参数是第二个参数,它是一个特定于IAdministrationRepository实例的服务/存储库

现在存在另一个名为意外事件报告控制器的控制器。 在其构造函数中,我执行与AdministrationController中相同的操作:

// When I now try to wrap my pupils into a ViewModel I have a problem:

IEnumerable<Pupil> pupils = incidentRepo.GetPupilIncidentReportDocumentList();         
PupilViewModels = new ObservableCollection<PupilViewModel>(pupils.Select(p => new PupilViewModel(p, ???)));
//当我现在尝试将学生包装到ViewModel中时,我遇到了一个问题:
IEnumerable products=incidentRepo.getpupilicindentreportDocumentList();
PupilViewModels=新的ObservableCollection(瞳孔选择(p=>新的PupilViewModel(p,p));
A.)或者我不想将服务传递给PupilViewModel,因为没有理由更新PupilViewModel中的属性,因为它在视图中是只读的

B.)在我的
管理控制器中
我从该
聚合中从服务获取数据
: 1
school class
有N个
学生
,1
学生
有N个
文档
。这些实体被包装成
SchoolclassViewmodels
PupilViewModels
DocumentViewModels

现在在我的
IncidentController
中,我也从服务中获取数据,我的
聚合
非常相似: 1
学生
有N
意外事故报告
和1
意外事故报告
有N
文档
。这些实体被包装成
PupilViewModels
IncidentReportViewModels
DocumentViewModels

问题是=>在PupilViewModel类中,它已经包装了一个DocumentListViewModel。现在,我需要再次使用PupilViewModel来包装IncidentReportListViewModel,然后我又有一个学生有一把椅子,并再次包装它们。这意味着我必须向PupilViewModel传递三个服务,尽管我并不总是需要它们

我很难直接切入问题的核心,但不知何故,我觉得这不是正确的方法


那么,我如何重新使用相同的ViewModel,该ViewModel使用具有不同服务的不同聚合来包装实体呢?

而不知道您在这条道路上走了多远……我强烈建议您看看是哪一个使用了。如Unitys网站所述

Unity应用程序块(Unity)为 轻量级可扩展依赖项 带支架的注射容器 构造函数、属性和方法调用 注射

在使用这些不同的框架时,您得到的是广泛的解耦和实例化的“职责”。然后,您不再需要担心参数被传递到构造函数中,因为框架将为您解析这些参数

例如,您还可以将已注册类型(例如IDoSomethingController)的生存期设置为实际类型(DoSomethingController),并将其生存期设置为在有人请求IDoSomethingController类型的对象时,如果您需要传递单个实例,则可以将其作为单个实例

一旦您使用了这些框架,您就不再“更新”一个实例,而是在利用该框架来提供您正在寻找的重用

IDoSomethingController controller = IUnityContainer.Resolve<IDoSomethingController>();
IDoSomethingController=IUnityContainer.Resolve();

编辑:由于您声明正在使用MEFedMVVM;DI框架存在。您的PupilViewModel是ObservableCollection的实例。这太过分了,把这个传过去。在您离开之前,ViewModel需要承担额外的重量,只需传递数据即可。您的ViewModels似乎试图表示对象和其他概念。我的意思是,你可以简单地拥有一个SchoolViewModel,它公开学生、班级等。。这些项成为模型,可以在ViewModel上以某种形式聚合。ViewModel是视图的中介。它可以包含各种模型和服务的丰富信息,成为视图的单一数据点。

我将回答我自己的问题,下面的问题或回答者请测试/检查我的解决方案,并评论它是否值得:

最初的问题是我在不同的上下文中在3个地方重用了PupilViewModel。一次PVM的ctor需要管理服务,另一次使用它需要意外事件报告服务,最后一次我忘记了第三个服务

现在,在所有3个地方注射所有3种服务对我来说都是愚蠢的:

PupilViewModel pVM = new PupilViewModel(pupil,adminService,IncidentReportingService,3rdService);
这样做3次看起来像是糟糕的架构。实际上我需要这个: 当我真的需要的时候,只需包好学生并注入所有3项服务

向下滚动,你们会看到MEFedMVVM可以执行Ctor和Prop注入
public SchoolclassViewModel(Schoolclass schoolclass, IAdministrationRepository adminRepo)
        {
            _schoolclass = schoolclass;
            _adminRepo = adminRepo;          

            //this.PropertyChangedHandler(object o, PropertyChangedEventArgs e)
            //{
            //    switch (e.PropertyName)
            //    {
            //        case "SchoolclassCode" : _saRepo.UpdateSchoolclass(_schoolclass); break;       
            //        default: break;
            //    }
            //}  

            PupilListViewModel = new ObservableCollection<PupilViewModel>();
            schoolclass.Pupils.ForEach(p => PupilListViewModel.Add(new PupilViewModel(p, _adminRepo)));
        }

        public IAdministrationRepository AdministrationRepository { get; set; }
PubilsViewModel(ISchool school) { }
var school = new School();
school.Save();
school.Update();
public class School
{
   private ISchoolRepository _repository;

   public string Name { get; set; }

   public School()
   {
      this._repository = IoC.Resolve<ISchoolRepository>();
   }

   public bool IsValid()
   {
     // Some kind of business logic?
     if (this.Name != null)
     {
       return true;
     }

      return false;
   }

   public void Save()
   {
      if (this.isValid())
      {
         this._repository.Save(this)
      }
}
// Knows it needs a school.
// When needing to start the save process for a School, would call the methods on the
// school instance provided in the constructor.
PupilViewModel(School school) { }

// Knows it needs a Repository.
// Would perform validation of business rules and call methods on the repository when//
// it is ready to be pursisted.
School(ISchoolRepository repository) {}

// Repository
// Would perform the read / write of the data.
SchoolRepository() {}