locked
UserControls (Views) not being truly 'disposed' after navigation event. RRS feed

  • Question

  • Hi all.

    I have a NavigationFrame sat within my MainPage.  However, after navigation event has fired (i.e. moved to another view/usercontrol), the orginal view does not appear to get truly disposed of.  

    I can tell that this is the case as the listeners I have registered on certain views are still firing even though the view themseles are not in use (or visible).  Furthermore, a number of events seem to fire multiple times if a view has been opened more than once,

    Does anyone know how to truly dispose of views that are not currently being used (ideally using an MVVM approach)?

    Many Thanks

    Tuesday, June 7, 2011 9:45 AM

Answers

  • Hi. The answer to your problem is already hidden in your post:

    the listeners I have registered on certain views are still firing

    As long as there are event handlers in the view that listen to event of other objects that are still in use, those other objects hold references to your views, and they will never be picked up by garbage collection. The solution is to either remove those event handlers completely (cleanup only happens if there's not a single reference left), or to get rid of both the view and (what I assume is) the corresponding view model at the same time (and recreate them when the user navigates back to the view), instead of keeping one part of the pair around longer than the other.

    We've had a discussion recently that had a very similar problem, maybe this helps you too.

    Tuesday, June 7, 2011 8:20 PM
  • I just need to 'Unregister' my messsage receievers/listeners

    This sounds much simpler than it actually is. For example, as soon as you're using data binding in your view, the binding engine listens to property changed events of the data context (i.e. the view model). It's next to impossible to do a clean-up of these links that takes all constellations into consideration. If you have a dynamic application where views get created and are supposed to be disposed regularly, I recommend to not use view model singletons, but create a new one for every new view. Whether you do that e.g. by creating them in Xaml or your view's code behind, or if you use some sort of IOC mechanism is rather a matter of taste and your requirements.

    which I know also implements ICleanup

    The ICleanup interface is not meant to prepare a view model for disposal. Here's a comment by Laurent to clarify this.


    Wednesday, June 15, 2011 7:26 AM

All replies

  • Hi. The answer to your problem is already hidden in your post:

    the listeners I have registered on certain views are still firing

    As long as there are event handlers in the view that listen to event of other objects that are still in use, those other objects hold references to your views, and they will never be picked up by garbage collection. The solution is to either remove those event handlers completely (cleanup only happens if there's not a single reference left), or to get rid of both the view and (what I assume is) the corresponding view model at the same time (and recreate them when the user navigates back to the view), instead of keeping one part of the pair around longer than the other.

    We've had a discussion recently that had a very similar problem, maybe this helps you too.

    Tuesday, June 7, 2011 8:20 PM
  • Thanks for your response.

    So, basically, I just need to 'Unregister' my messsage receievers/listeners once my view/viewmodel is navigated away from.  Then the view/viewmodel will be completely disposed of.

    Is it possible to place an onNavigatedFrom method within my viewmodel in order to unregister the message recievers (they are often registered in the viewmodel iteself)?

    I am using MVVM Light which I know also implements ICleanup, however, I am unsure how to use this.  Can someone possibly give me some pointers? 

    Many Thanks


    Wednesday, June 15, 2011 6:51 AM
  • I just need to 'Unregister' my messsage receievers/listeners

    This sounds much simpler than it actually is. For example, as soon as you're using data binding in your view, the binding engine listens to property changed events of the data context (i.e. the view model). It's next to impossible to do a clean-up of these links that takes all constellations into consideration. If you have a dynamic application where views get created and are supposed to be disposed regularly, I recommend to not use view model singletons, but create a new one for every new view. Whether you do that e.g. by creating them in Xaml or your view's code behind, or if you use some sort of IOC mechanism is rather a matter of taste and your requirements.

    which I know also implements ICleanup

    The ICleanup interface is not meant to prepare a view model for disposal. Here's a comment by Laurent to clarify this.


    Wednesday, June 15, 2011 7:26 AM
  • OK, I had the same problem, and solve it casting my LayoutRoot.DataContext wich is a ViewModel and then calling the cleanup method there:

    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        var vm =(this.LayoutRoot.DataContext as MyViewModel);
    
        vm.Cleanup();
        base.OnNavigatingFrom(e);
    }
     
    let me know if it helped


     

    Wednesday, June 15, 2011 7:34 PM
  • This doesn't clean the references the view model holds of the view through event listeners.

    Thursday, June 16, 2011 2:55 AM