How to create a ViewModel with MEF container?

Aug 24, 2011 at 8:46 PM

Hello,

May I ask for a suggestion in the following scenario?

Let's say I want to make a NotePad-like editor able to open several text files in a tab control (which not really true, but reflects the issue). I suppose that for each opened document, there should be kind of a TextDocumentViewModel. If the user clicks "New" button, a new TextDocumentViewModel should be created as well with appropriate data.

The thing I don't understand is how exactly I should create that new instance of TextDocumentViewModel class. In your MEFedMVVMDemo all ViewModels are created, only when the View requests them in XAML. There you have no UserViewModel actually and this is the difference. While, in the MEFedMVVMDemo it seems enough to use User model directly, I can't do the same (my model is an interface = no templating).

How am I supposed to instantiate a new ViewModel, so that it gets composed by MEF? I have an incomplete idea for that (I'll use code from the Demo, as if we wanted to create UserViewModel):

 

		[MediatorMessageSink(MediatorMessages.AddUser, ParameterType=typeof(User))]
		public void OnAddNewUser(User newUser)
		{
UserViewModel userVM = ViewModelRepository.CreateUserViewModelSomehow(...);
userVM.UserModel = newUser;
  _userVMs.Add( userVM); }

 

  • Is this a reasonable approach at all?
  • How to get the ViewModel, when there is no contract name available? new UserViewModel() is not a solution, because it won't be composed, so the ViewModel won't have access to goodies like IMediator, etc. 
  • Another example of the same issue: In some parts of my app, I'll need to trace changes in the model and automatically reflect them in GUI. E.g. an external extension adds an item to a collection somewhere and a new view representing that item should appear on the screen. In my understanding this is done by creating a new ViewModel instance that wraps the item. Again, I'm not sure how to compose the ViewModel in such a case. Is it doable at all with MEFedMVVM approach?

Thanks in advance.

 

TextDocumentViewModel
Coordinator
Aug 26, 2011 at 9:35 AM

This is the typical ViewModel-First approach vs View-First approach.

View first is easy... link it to the view and voila everything just works... when you want to create a ViewModel from another ViewModel the control is all in your hand. So yes you will have to call the new UserViewModel() the parameters such as Mediator etc you can get them from the parent ViewModel itself... 

i,e

 

public ParentViewModel(IMediator mediator)
{ _mediator = mediator; }

public void OnAddNewUser(User newUser)
{

   UserViewModel userVM = new UserViewModel(_mediator); 

 

Now where it gets a bit complicated is when you want to use services such as IVisualStateManager since these services are IContextAware i.e. they are UI services and need to have the instance of the View that is using that ViewModel. For that you can decorate your ViewModel with ExportViewModel as usual BUT you specify that it is ViewModel first i.e

[ExportViewModel("UserVM", true]
public class UserViewModel

You then put in your view the ViewModel locator stuff as usual so that MEFedMVVM can still map a ViewModel to the View. When using this feature MEFedMVVM will not create an instance of the ViewModel at runtime BUT it will resolve any property that has the [Import] attribute, so if you want to get the instance of IVisualStateManager you do it in a property instead of the constcurtor

[Import]
public IVisualStateManager  VSM {get;set;}

This approach is explained in the last section of this post
http://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/

 

Hope this helps 

 

Aug 26, 2011 at 5:38 PM

Thanks for your explanation. It helped a lot. Indirectly it cleared some of my other doubts actually. Things in MEFedMVVM are smarter than I thought.

Coordinator
Aug 26, 2011 at 6:59 PM

now a new cool feature is coming up... tonight I will be coding it up :) resolving views and passing parameters to their ViewModel :) it will be awesome :)

Aug 26, 2011 at 7:18 PM

I'm glad to hear that. I like new features :) Looking forward to seeing it!