1

I'm using MVVM Light in a simple WPF application. I understand that the ViewModelLocator class can be used to create cached view model objects, both with & without a key. However, I want to be able to create a view model that isn't cached or keyed. Let me elaborate.

I have a new dialog in my application. The dialog contains a ComboBox that has a list of choices, an OK button & a Cancel button. I tried adding a property to the ViewModelLocator for the new dialog's view model object like this:

public NewObjectViewModel NewObject {
    get { return ServiceLocator.Current.GetInstance<NewObjectModel>(); }
}

This worked, but if I opened the new dialog once, made a choice and clicked OK, then opened it again later, the user's previous choice was already selected. This is not what I want. I want the new dialog to be in exactly the same initial state each time its opened.

Do I just replace the call to ServiceLocator.Current.GetInstance<NewObjectModel>() with a call to new NewObjectModel()? Or is there a different call of ServcieLocator.Current that I need to use?

This is a simple example, as this view model class's constructor takes no parameters. I have another dialog that takes an IDataService reference as a parameter. It has a second parameter, which is a MyModel object. It seems that the whole pattern doesn't work in this case, as you can't pass the model object into the property, and the model object is a property of the MainViewModel class.

How do I use the ViewModelLocator correctly in these two cases?

Edit:

I've done some more searching & I've found that the SimpleIoc class has a GetInstanceWithoutCaching<T>() method, which works for my new dialog. So that's half the question.

But how do I handle the case of creating a new view model, using ViewModelLocator, for a view model class whose constructor takes a model object as a parameter?

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123

1 Answers1

1

I've been able to find a solution to my problem that works and is pretty elegant.

First, as I said in the edit to my question, I found the GetIntanceWithoutCaching<T>() method in the MVVM Light SimpleIoc class. This method creates a new instance of the class whose type is passed in T every time it is called.

Second, I found this blog post which describes a process for the view model of the child dialog to send a message back to the main view model that requests the receiver send it the model object it needs. Here are all of the changes I had to make to my code to get this to work.

First, I created a new message class:

public class GetMyModelMessage : MessageBase {

    public Action<MyModel> Callback { get; private set; }

    public GetMyModelMessage( Action<MyModel> callback ) {
        Callback = callback;
    }
}

Then, in the MainViewModel:

public MainViewModel() {
    // Existing initialization code

    Messenger.Default.Register<GetMyModelMessage>( this, SendMyModel );
}

private void SendMyModel( GetMyModelMessage message ) {
    message.Callback( MyModelProperty );
}

In the constructor of the view model for the child window:

public ChildViewModel() {
    // Existing initialization

    Messenger.Default.Send( new GetMyModelMessage( m => MyModelProperty = m );
}

Finally, in the ViewModelLocator:

public ChildViewModel Child {
    get { return SimpleIoc.Default.GetInstanceWithoutCaching<ChildViewModel>(); }
}

With all of these changes, the XAML for the child window can now set the DataContext the same way the main window does, a new view model for it is created by the ViewModelLocator when the child window is created, the child view model sends a request for the model object to display. The child view model doesn't know who will handle the message, just that it gets an object to display through the callback in the message.

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123