WPF/MVVM:在多控制器和关注点分离中重用ViewModel
在myAdministration Controller中,我使用了一个PupilViewModel类似: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
_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.)在我的管理控制器中
我从该聚合中从服务获取数据
:
1school 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() {}