My Model is a generic class that contains a (for example) Value property which can be int, float, string, bool, etc. So naturally this class is represented something like Model<T>. For the sake of collections Model<T> implements the interface IModel, although IModel is itself empty of any content.
My ViewModel contains and instance of Model<T> and it is passed in through ViewModel‘s constructor. I still want to know what T is in ViewModel, so when I expose Model to the View I know the datatype of Model‘s buried Value property. The class for ViewModel ends up looking like the following:
class ViewModel<T>
{
private Model<T> _model;
public ViewModel(Model<T> model) { ....blah.... }
public T ModelsValue {get; set; }
}
This works fine, but is limited. So now I need to expose a collection of IModels with varying Ts to my View, so I’m trying to set up an ObservableCollection of new ViewModel<T>s to a changing list of IModels. The problem is, I can’t figure out how to get T from Model<T> from IModel to construct ViewModel<T>(Model<T>) at runtime.
In the VS2010 debugger I can mouseover any IModel object and see its full Model<int> for example at runtime so I know the data is in there.
Any ideas?
Here’s what I’m using for view model collections:
Preface:
Your view model objects can be weakly typed. Give
IModela propertyobject Value {get;}and expose that in aModelViewModel : ViewModel<IModel>that you use for allIModelobjects (see myViewModel<T>implementation below). If you have various combinations ofObservableCollection<IModel>,ICollection<Model<T>>, etc., the framework shown here is a lifesaver. If you still need generic view model, you can derive aModelViewModel<T> : ModelViewModelthat takes aModel<T>in its constructor. The logic to create the appropriate type would go in the converter passed toViewModelCollection.Createbelow. Do be warned that this design will impose a performance penalty.Example usage:
Benefits:
INotifyCollectionChangedif the underlying model collection implementsINotifyCollectionChanged.Overview of the classes (full implementations linked to github):
ViewModel<TModel>: Base class for my view model classes. Exposes aModelproperty that I use in the view model’s backing code.ObservableViewModelCollection<TViewModel, TModel>: Lazy (actually not currently, but definitely should be), observable mapping from a model to a view model. ImplementsINotifyCollectionChanged.ViewModelCollection<TViewModel, TModel>: Lazy mapping from a collection of TModel to a collection ofTViewModel.ViewModelCollection: Static helper – returns anICollection<TViewModel>, usingObservableViewModelCollection<TViewModel, TModel>when the source collection implementsINotifyCollectionChanged, otherwise usingViewModelCollection<TViewModel, TModel>.A few extra types that might be useful for your view model collections:
ConcatCollection: Like ViewModelCollection, this includes a static helper to automatically choose an appropriate implementation. The ConcatCollection concatenates collections by binding directly to the source collection(s).ConcatCollectionConcatCollection<T>ObservableConcatCollection<T>Here is an example of how I used this type to expose a
Childrenproperty to the view while maintaining my observable collections all the way to back to the original source.