MVVM: Handling logical child objects of models in collections
Using MVVM, one type of ViewModels include the Model they represnt as a Field.
So I do have a CompanyModel and a CompanyViewModel that has one instance of CompanyModel.
This CompanyModel has a collection of Divisions belonging to it. So CompanyModel has a List (or some collection class).
Now the CompanyViewModel would want to represent these Divisions as an ObservableCollection<DivisionViewModel>
; and you you could add new Divisions in the CompanyViewModel.
What is the best way ensure that the ObservableCollection and the Models collection stay in sync? So when I add a new DivisionViewModel and save it, it automatically saves its model to the CompanyModel's List<Division>
?
I have more classes like this Parent/child relations so I would love something I could reuse or implement perhaps in a AbstractViewModel class.
Note: My ViewModels impleme开发者_C百科nt IEditableObject
Probably the easiest way to do this is to create a new class that inherits from ObservableCollection, and which takes a source list and various initialization and mapping functions as parameters. Its signature might look something like this:
public class SynchronizedObservableCollection<TDest, TSource> : ObservableCollection
{
public SynchronizedObservableCollection(
IList<TSource> source,
Func<TSource, TDest> newDestFunc,
Func<TDest, TSource> newSourceFunc),
Func<TSource, TDest, bool> mapSourceToDestFunc
{
// Initialize the class here.
}
}
You'd then want handle the CollectionChanged event, creating new Source instances when a new Destination instance got added, deleting existing Source instances when an existing Destination instance got deleted, that sort of thing. You'd use the "new" functions above to create new instances of the various entities, and you'd use the "map" functions above in various Linq queries that would allow you to figure out, say, which instance of a viewmodel your ObservableCollection mapped to a model in your List.
You would use it in your example above like so, perhaps:
var divisionViewModels = new SynchronizedObservableCollection(
company.DivisionList,
division => new DivisionViewModel(division),
divisionVm => divisionVm.Model,
(division, divisionVm) => divisionVm.Model == division);
The exact implementation is left as an exercise to the reader :-). But I've used classes like this with some success in previous projects. Just make sure you work up some good unit tests around it, so that you know you can rely on it, and don't have to spend a lot of time hunting through event-handling callstacks.
精彩评论