memory leak, closing child usercontrols

Topics: Prism v4 - WPF 4
Jan 20, 2014 at 1:08 PM
Edited Jan 20, 2014 at 1:09 PM
I am using Prism, .NET 4.0 and MVVM pattern.
I am having a problem with a window that has three usercontrols.
When I close the window, the usercontrols are still alive (even though I have set IsNavigationTarget to return false (from INavigationAware) and KeepAlive return false to (from IRegionMemberLifeTime)).
So I tried overriding the OnClosing event from my window, buth this also didn't work.
When I removed the view from the region I get an error:
"The region does not contain the specified view.
Paramtername: view"
, when I deactivated the view they just stay alive and keep using up memory.
Is there a fix or work around for my problem?
To be complete, this is what my Code looks like:
ViewModel from one of my three UserControls: (most of my code filtered out, buth important one for this issue is still there)
public class OverzichtMeldingenViewModel : Catel.MVVM.ViewModelBase, IOverzichtMeldingenViewModel, INavigationAware, IRegionMemberLifetime
        private readonly IUnitOfWork uow;
        private readonly IServiceLocator sl;

        public OverzichtMeldingenViewModel(IServiceLocator servicelocator)
            uow = new UnitOfWorkFactory();
            sl = servicelocator;
#region INavigationAware Members
        public bool IsNavigationTarget(NavigationContext navigationContext)
            return false;
        public void OnNavigatedFrom(NavigationContext navigationContext)
            //do nothing
        public void OnNavigatedTo(NavigationContext navigationContext)
#region IRegionMemberLifetime Members
        public bool KeepAlive
            get { return false; }
xaml from my parent Window:
<Window x:Class="S20_Workflow_MvvM.WPF.ModuleMeldingenView"
   <Grid Name="gridRoot">
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        <ContentControl Grid.Row="0" Grid.Column="1" prism:RegionManager.RegionName="Workflow"/>
        <ContentControl Grid.Row="1" Grid.Column="1" prism:RegionManager.RegionName="OverzichtView"/>
        <ContentControl Grid.RowSpan="2" Grid.Column="0" prism:RegionManager.RegionName="NavigatieView"/>
code-behind from my window:
public partial class ModuleMeldingenView : Window
        private IModuleMeldingenViewModel vm;
        private IRegionManager rm;

        public ModuleMeldingenView(IModuleMeldingenViewModel vm,IRegionManager rm)
            this.vm = vm;
            DataContext = this.vm;
            Closing += this.vm.afsluitenMelding;
            Closing += Scherm_Closing;
            this.rm = rm;

        private void Scherm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            List<SchermSettings> settings = null;
            using (IUnitOfWork UnOfWo = new UnitOfWorkFactory())
                var user = LoginClass.getInstance().HuidigeGebruiker;
                if (user != null)
                    var type = this.GetType().ToString();
                    settings = UnOfWo.Repository<SchermSettings>().GetAll().Where(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type)).ToList();

                    if (settings != null && settings.Any())
                        UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("Height")).Waarde = this.Height.ToString();
                        UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("Width")).Waarde = this.Width.ToString();
                        UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("Left")).Waarde = this.Left.ToString();
                        UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("Top")).Waarde = this.Top.ToString();
                        switch (this.WindowState)
                            case WindowState.Minimized:
                                UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("WindowState")).Waarde = "Minimized";

                            case WindowState.Maximized:
                                UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("WindowState")).Waarde = "Maximized";

                                UnOfWo.Repository<SchermSettings>().GetAll().FirstOrDefault(s => s.USER_ID == user.USER_ID && s.Scherm.Equals(type) && s.Parameter.Equals("WindowState")).Waarde = "Normal";
            Closing -= vm.afsluitenMelding;
            Closing -= Scherm_Closing;

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
            var view = rm.Regions["Workflow"].ActiveViews.FirstOrDefault();
            if (view != null)
            view = rm.Regions["OverzichtView"].ActiveViews.FirstOrDefault();
            if (view != null)
            view = rm.Regions["NavigatieView"].ActiveViews.FirstOrDefault();
            if (view != null)
Thanks in advance for the replies ;)
Jan 20, 2014 at 5:49 PM
Hello DSO,

First, I would like to say that Prism uses a Garbage Collector in order to clear and control memory usage of the App. But it would not be possible for developers to know when the collector would run and free memory space like the user controls in this scenario. Therefore, I suggest you to perform some kind of performance test in order to verify this behavior or if there really is a memory leak.

However, it may happen for the View to stay alive for the following reasons:

  • The Views are saved in the container as Singletons, so the container will hold an instance (the Singleton instance) of the Views as long as the container itself is kept alive.
  • The related ViewModels are stored as Singletons, and the corresponding Views are tight coupled to them with an event subscription for example.
  • If using Interaction Requests, a strong reference to the View could be holded, as there is a known issue where using Interaction Requests creates memory leaks, so the View is never destroyed.
If this does not solve your problem, it would be helpful if you could provide us with a repro-sample application portraying this problem, so we could get a better understanding of your scenario and help you find the cause behind this problem.

I hope this helped you,

Gabriel Ostrowsky
Jan 21, 2014 at 12:14 PM
Edited Jan 21, 2014 at 12:18 PM
I know the Carbage Collectors works when it wants, buth I am using a memory profiler to see how maney instances of an object exists in my memory.
With this profiler, I can also make the garbage collector do it's job (meaning cleaning up the unused objects).
Buth when I close a window with 2 usercontrols inside, the windowinstance is closed buth the usercontrols stay alive.
I also made a small example : TestMemory .
When I click the button (press me) , a new window is opened with 2 usercontrols in it. When I close that window, the usercontrols stay alive.
In my current application this means alot of wasted memory use since my viewmodels containt alot of objects.
Iff you are wondering what I use, it's the Memory Profiler from Telerik 's JustTrace.

Thanks for the help in advance.
Feb 5, 2014 at 5:07 PM

I have checked your sample and reproduced the memory leak you are experiencing. I also saw that you are using a modified version of the DialogActivationBehavior of the StockTrader RI for this sample. As far as I know, this functionality was not prepared to be used in complex scenarios such as popup windows with multiple regions inside and in fact, the popup region doesn't event contains the default prism behaviors that the rest of the regions have as out of the box.

That being said, closing the popup window will not remove the views of the inner regions. You will need to do this manually.
In the following folder you can find a modified version of your sample where the ParentViewModel, MainViewModel and NavigationViewModel are being garbage collected correctly:
The main diferences you will find in this modified version are:
  • I changed the DialogActivationBehavior to be more close to how the original behavior was. As a result, I also needed to convert the ParentView into a UserControl.
  • The RegionPopupBehavior now populates the region with Prism's behaviors. This is to allow us to use funtionalities like IActiveAware and IRegionMemberLifetime.
  • The ParentViewModel now implements IActiveAware and deactivates the inner views when it's deativated.
  • Also, I needed to make the MainViewModel inherit from Prism's NotificationObject. For some reason, inheriting from Catel's ViewModelBase was causing the view model to be kept alive.
In the sample you will also find a "Check alive" button. When clicked an event is fired and if any of the three view models mentioned above is alive, they should print a line in the Output window.

I hope this helps,

Damian Cherubini