我们最近遇到了类似的问题,但附加要求模型由简单愚蠢的 POCO 组成。
我们的解决方案是粗暴地应用 Model-ViewModel 分离。Model 和 ViewModel 都不包含ObservableCollection<ModelEntity>
,而是 Model 包含 POCO 集合,而 ViewModel 包含ObservableCollection<DetailViewModel>
.
这很容易解决了添加、获取和更新。此外,如果只有 Master 从其集合中删除一个细节,则会触发适当的事件。然而,如果细节请求被删除,它必然需要通知主人(集合的所有者)。
这可以通过滥用PropertyChanged
事件来完成:
class MasterViewModel {
private MasterModel master;
private ISomeService service;
private ObservableCollection<DetailViewModel> details;
public ObservableCollection<DetailViewModel> Details {
get { return this.details; }
set { return this.details ?? (this.details = LoadDetails()); }
}
public ObservableCollection<DetailViewModel> LoadDetails() {
var details = this.service.GetDetails(master);
var detailVms = details.Select(d =>
{
var vm = new DetailViewModel(service, d) { State = DetailState.Unmodified };
vm.PropertyChanged += this.OnDetailPropertyChanged;
return vm;
});
return new ObservableCollection<DetailViewModel>(detailVms);
}
public void DeleteDetail(DetailViewModel detailVm) {
if(detailVm == null || detailVm.State != DetailState.Deleted || this.details == null) {
return;
}
detailVm.PropertyChanged -= this.OnDetailPropertyChanged;
this.details.Remove(detailVm);
}
private void OnDetailPropertyChanged(object s, PropertyChangedEventArgs a) {
if(a.PropertyName == "State" & (s as DetailViewModel).State == DetailState.Deleted) {
this.DeleteDetail(s as DetailViewModel);
}
}
}
class DetaiViewModel : INotifyPropertyChanged {
public DetailState State { get; private set; } // Notify in setter..
public void Delete() {
this.State = DetailState.Deleted;
}
public enum DetailState { New, Unmodified, Modified, Deleted }
}
public event Action<DetailViewModel> Delete;
相反,您可以在 中引入一个DetailViewModel
,将其直接绑定到MasterViewModel::Delete
等。
这种方法的缺点是您必须构建许多 ViewModel,这些 ViewModel 可能永远不需要超过它们的名称,因此您确实需要保持 ViewModel 的构建成本低廉,并确保列表不会爆炸。
从好的方面来说,您可以确保 UI 仅绑定到 ViewModel 对象,并且您可以将大量 INotifyPropertyChanged goop 保留在您的模型之外,从而使您在层之间有一个清晰的界限。