1

I'm bit confused with the behavior of my code. I'm still newbee in MVVM light.

I have NewMessageWindow which is shown by command

    private ICommand newMessageCommand;
    public ICommand NewMessageCommand
    {
        get
        {
            if (newMessageCommand == null)
                newMessageCommand = new RelayCommand(() =>
                {
                    new NewMessageWindow().Show();
                });
            return newMessageCommand;
        }
    }

There can be multiple NewMessageWindows and each of them should have separate ViewModel. But I've noticed when I open multiple windows and if I change something in them it affects all windows. For example when I change combobox then combox values changes in all windows.

How to avoid it? How can I open multiple windows with seprate viewmodels that wouldn't affect each other?

Objects that are changing are ObservableCollections that are bound to view.

Edit:

This is how the ViewLocator looks like

    public NewMessageWindowModel NewMessage
    {
        get
        {
            return ServiceLocator.Current.GetInstance<NewMessageWindowModel>();
        }
    }

and in constructor

    SimpleIoc.Default.Register<NewMessageWindowModel>();

This is how binding looks like:

 DataContext="{Binding NewMessage,
                          Source={StaticResource Locator}}"

I've fixed problem with

 ServiceLocator.Current.GetInstance<NewMessageWindowModel(System.Guid.NewGuid().ToString());

but I've read that old instances are cached. How to get rid of them?

12
  • 1
    Does each view have it's own viewmodel? If the views all have the same viewmodel, then your INofifyPropertyChanged (Or your similar MVVM implementation) will notify all of the windows and change accordingly. Commented Jul 8, 2013 at 12:49
  • how can I check it? They are all extending ViewModelBase Commented Jul 8, 2013 at 12:52
  • Without seeing more code it's hard to tell; I'm assuming your views are XAML windows, are you setting each one's datacontext to that of a different view model? Commented Jul 8, 2013 at 12:53
  • well where do you create the VM for NewMessageWindow ? that's where you check if it does indeed create new VM's per View instance Commented Jul 8, 2013 at 12:53
  • They are xaml windows this is how I set dataContext DataContext="{Binding NewMessage, Source={StaticResource Locator}}" Commented Jul 8, 2013 at 12:54

2 Answers 2

1

SimpleIoC from MVVM Light does not create a new VM per call with ServiceLocator.Current.GetInstance<...>();

You can find the explanation from the library's author to get a new VM each time Here

For your case,

I'd probably just set the DataContext in the code-behind constructor of NewMessageWindow than directly in xaml with something like:

public NewMessageWindow() {
  InitializeComponent();
  var uniqueKey = System.Guid.NewGuid().ToString();
  DataContext = SimpleIoc.Default.GetInstance<NewMessageWindowModel>(uniqueKey);
  Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
}

This way when the Window is closed, the VM will be removed from the cache.

Do note this is not the only way to do this, you have quite a few other options,

  • You can keep the binding in the xaml for DataContext and when the Window is closed, using the Messenger class in MVVM Light send a message to the ViewModelLocator to remove the cache.
  • You can implement the Cleanup() function in the ViewModelLocator to remove the cache when presented with a key.

Pick an implementation that you prefer and go with it or use something like Unity or other DI-container helpers to get even more control of VM object lifetime's.

Sign up to request clarification or add additional context in comments.

3 Comments

I've put the code in view and it doesn't work, the only solution that works is to use return ServiceLocator.Current.GetInstance<NewMessageWindowModel>(System.Guid.NewGuid().ToString()); but in that way I don't know how to get rid of cached window.
@Robert I've made a few edit's in the code paste, you sure you copied the latest? also make sure to remove the xaml binding for DataContext from NewMessageWindow.xaml
After your edited code it works. I'll accept the answer. Thank you for your time.
0

This behaviro is because of the Servicelocator. which return the same instance of the object. where you get the changes all over the shared instances. If you want to have a saperate copy of you ViewModel. You coudl implement the GetNewInstance into Service locator.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.