We recently ran into a similar problem, but with the additional requirement that the model consist of simple stupid POCOs.
Our solution is to brutally apply Model-ViewModel separation. Neither the Model nor the ViewModel contain an ObservableCollection<ModelEntity> , instead the model contains a POCO collection, and the ViewModel contains an ObservableCollection<DetailViewModel> .
This easily resolves Add, Get, and Update. Also, if only the Master removes the part from the collection, the corresponding events are triggered. However, if the request details must be removed, it is imperative to inform the master (collection owner).
This can be done by breaking the PropertyChanged event:
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; }
Instead, you can enter public event Action<DetailViewModel> Delete; in DetailViewModel , bind it directly to MasterViewModel::Delete , etc.
The disadvantage of this approach is that you need to build a lot of ViewModels that you might never need for more than their name, so you really need to keep the ViewModels construct cheaper and make sure the list doesn't explode.
At the top, you can make sure that the user interface is only associated with ViewModel objects, and you can save a lot of INotifyPropertyChanged goop from your model, giving you a clean slice between layers.
M.Stramm
source share