Cleanup/disposal of views and view models

Topics: Prism v4 - WPF 4
Sep 5, 2013 at 1:43 PM
Apologies in advance for the long post. I'm having a hard time understanding if/how/when views and view models are cleaned up and GC'd/disposed.

Some background on my app: it's WPF and Prism 4.1, and I'm using Castle Windsor as my IoC. The app consists of a "main" window containing a region into which I load a "results" view. The "results" view contains a number of regions of its own - these always show the same view, so they are loaded using the "regionManager.RegisterViewWithRegion" notation during application startup. These child regions do not participate in navigation at runtime.

All views and view-models are registered with Castle as "transient". View-models are decorated with the "[RegionMemberLifetime(KeepAlive = false)]" attribute, and the views include the "ClearChildViewsRegionBehavior.ClearChildViews="True"" attached property. View-models are injected into their corresponding view's constructor (I believe this is "view first"?).

Despite all this, if I navigate away from the "results" view (using regionManager.RequestNavigate), it seems that neither this view/VM, or any of its child views/VMs are being GC'd/disposed. I've tried implementing IDisposable on all the views and VMs, but Dispose() never gets called.

My main concern is to avoid memory leaks - my "results" view, and its child views, render a huge amount of information (based on records in a db), and if the user continually navigates in and out of this view, viewing these records, it's going to eat up memory. Also, I've implemented an "events service" (similar to Prism's event aggregator) where the VMs register as event publishers and/or subscribers. I'm finding that even after navigating away from the "results" view, its VM and the child VMs, are still responding to events - further evidence that things aren't being cleared up.

I guess I need some way for the child VMs to cleanup, including unsubscribing from these events, when the parent "results" view is navigated away from, but how/where? IDisposable.Dispose() seemed like the ideal place, but it's not being called - whether that's down to Castle or Prism, I don't know.

One other option might be to change my approach and register all the views and VMs as "singletons", avoiding such memory concerns. However I still might want to perform some cleanup on the child VMs, so how/where could I do that?

Thanks in advance
Sep 5, 2013 at 3:57 PM
Hi,

Based on my understanding, the RegionMemberLifetime attribute is only in charge of telling if the VM has to be removed from the Region or not, which does not force the destruction of the VM. Therefore, the root of your problem is more likely to be related to the "events service" you implemented, since the subscription to these events are strong references to your VMs which causes them to be kept alive and responding to events.

In order to be able to resolve this, you can choose between the following 2 options:

  • Make your VMs implement IActiveAware which provides the IsActive property. Then, in the setter of the property you verify if its value and RegionMemberLifetime are false so you can do the cleanup.
  • On the other hand, you can make your VMs implement INavigationAware and the just check if RegionMemberLifetime is false in the OnNavigatedFrom method (provided by INavigationAware) and do the cleanup there.
Hope this helps,

Federico Martinez
http://blogs.southworks.net/fmartinez