strange behaviour with PropertyChanged

Feb 1, 2012 at 7:53 PM

Hi,

 

I found a strange behaviour (concerning the binding view <-> viewmodel): In my silverlight 5 application (should also be the same in 4), I can switch between several views (each of them are bound to a viewmodel). When I change a property on view1, the propertychanged is raised exactly one time (as expected). When I change to another view and load view1 again and change the property another time, the propertychanged is called twice...if I repeat this, it is raised three times and so on - I can't figure out why...has anybody else had this issue?

Coordinator
Feb 18, 2012 at 3:00 PM

Just a hunch, but the lifetime of a viewmodel is usually tied to that of a view.  The ViewModelLocator generally creates a ViewModel "on demand" as a property getter.  If you have more than one View per ViewModel, you are most likely getting multiple instances of the ViewModel, one per View.  Try changing the ViewModelLocator property to only create a ViewModel if it has not already been created.  Then all Views will share the same instance of the ViewModel.  However, you will also need some clean-up code, to set the member variable for the ViewModel in the locator to null when all the views using it have been closed.  Hope this helps!

Tony

Feb 20, 2012 at 1:28 AM

Just curious, what happens when if you set the NavigationCacheMode=Required for the view? Will be still create new viewmodels? It seems to be working fine with my Navigation app. 

When can we expect the toolkit for Silverlight 5? Can't wait. ;-)  - With all the UI controls are now released for Silverlight 5 and I can't use them :( 

Coordinator
Feb 29, 2012 at 1:49 AM
By default the lifetime of a ViewModel is tied to the View it is bound to. The ViewModelLocator property creates the ViewModel on the fly in a getter. When the View goes out of scope, and is no longer referenced, it is garbage collected, and the ViewModel is as well.

This dynamic changes when you cache the View. In this case the View continues to live, align with it's ViewModel. That may be a good thing, if you want to preserve the state of the View, but it can also lead to increased memory consumption, as more and more views are created but not destroyed. So I would recommend using this technique with caution and implementing a clean-up mechanism of some kind, where you go back and explicitly get rid of Views no longer need to have in cache.

Cheers,
Tony
Feb 29, 2012 at 1:59 AM

Thanks Tony! I have now disabled the NavigationCacheMode to all of the pages except for one main page which I need to be cached so all the initial information entered by the user is preserved. This app is a form of wizard where user inputs values in the first page and the subsiquent pages depend on the main page. Thanks for the clarification. I also noticed that the Loaded method is called even even when the NavigationCacheMode is set to "Required'.

Anyway, I have been using the RegisterToReceiveMessages method to get updates rather than do things on load. Works fine. Thanks for the wonderful tool once again.

Jun 28, 2012 at 7:24 AM

Hi Tony,

It all looked well and fine until I did some memory profiling for the application. I was wondering as to why the page was longer to load each time I navigate to the page. The profiling shows that the instance of viewmodel and view increases by 1 every time I load the page.

  • I have a wizard like application with the selected page is controlled by the selected item of the listbox.
  • I have set the NavigationCacheModel to Disabled in all of my pages so that it gets a new viewmodel every time a page is loaded.
  • I store the main class in NavigationHelper when the page in unloaded
  • This class is loaded when the new page is loaded by registering to listen to the "datasaved" event fired by the hosting page.

Is there anything I need to consider so that the when I navigate to new page the old view/viewmodel is garbage collected so I only have one instance of the viewmodel at a time? This is a real issue if the user navigates back and forth in the application as it generates large number of views/viewmodels and chews up memory.

Any help is appreciated.

P.S. I have one viewmodel per view.