Can you manually deactivate/dispose a ViewModel?

Topics: Conventions, Getting Started
May 11, 2013 at 1:03 AM
In a current project I am working on I have a ShellVM that is a Conductor. One of it's containd VMs has two separate <ContentControl/> elements bound to properties that are initially null, but filled/cleared when certain events occur.

The VM handles a message from the EventAggregator, dynamically creating a child VM and sticking it into the right property. Because of this, it is not managed by a conductor (though it does inherit screen). When the VM gets the clear message, it sets the property to null, clearing the <ContentControl/>, but the viewmodel lives on in the background, causing trouble.

I tried TryClose() and Deactivate(), but they don't do anything. I can add IDisposable to the ViewModel and just call .Dispose(), but I was wondering if there was a good/standard way in CM to handle this.

If the answer is to use a Conductor, what would be the conductor, as this VM has more sub-VMs than just the two <ContentControl/> elements.

May 12, 2013 at 10:40 AM
You are correct in assuming you should manually dispose. Because of the potential complexity of screen lifecycle Caliburn.Micro makes no assumptions with regard to lifecycle management. This essentially means that we recognise the difference between Close, Deactivate and Dispose.

Many applications keep their ViewModels in the background for caching purposes and override the Deactivate() method to essentially put a viewModel to sleep (turning off services) for example, you could unsubscribe the viewModel in question from the EventAggregator and resub on Activate.

If you do wish to Dispose() you could override screen and call Dispose in Deactive() on ViewModels which require this. However, this is something to be careful with. I would be more inclined to flesh out a ViewModel's lifecycle in terms of Activation / Deactivation rather than destroy it and create it over and over.
May 12, 2013 at 10:47 AM
I just wanted to pick out something too:

If you created a child vm and then set it to null, it should eventually get disposed by default. The absence of this behaviour suggests that perhaps something else is holding on to the child vm also?
May 12, 2013 at 8:08 PM
Thanks for the replies. The "parent" VM that is in a conductor stays alive throughout the application (it handles the messages), but the "child" VMs that are not in conductors are created manually and I just hold one reference to them until i need to get rid of them.. I assumed they would be GC'd automatically, but maybe not fast enough for me. They have a dependency that polls the serial ports and spits out logging, so it's clear that they don't dispose right away.

The easiest thing is probably manually dispose them and clean up the dependency.