Watch out how you format that navigation string

Related Platforms: Silverlight and Windows Phone 7

The Problem

I’ve noticed that the constructor on my MainPage was being called again, when I navigated back to the MainPage using the NavigationService.

NavigationService.Navigate("/Views/MainPage.xaml");
This manifested itself, by events getting fired multiple times, which is undesirable on multiple levels. Events being called multiple times can cause unnecessary web calls, more cpu and memory usage, thus leading to more battery usage and potentially a bigger bill for the user.

Background

I didn’t understand, why MainPage constructor would be called twice. I’ve read in multiple sources that your MainPage survives as long as the app does. Then I stumbled in to a post, which shed some light to the issue. If you navigate to the same page, but using a different query parameters, then a new version of that page is instantiated again. More details on this issue can be found here: http://social.msdn.microsoft.com/Forums/en/windowsphone7series/thread/90f6a71d-a856-4b00-afe6-97e67b411417

This is marginally okay behavior, if you’ve recreated the ViewModel for each instance of a page aka Satellite ViewModels. However, you may have noticed that in the default project template, your MainViewModel is statically associated to your App.xaml. For more information on this, I highly recommend reading all three articles of this series: http://www.imaginativeuniversal.com/blog/post/2010/08/15/Patterns-of-Windows-Phone-Architecture-Part-1.aspx

Solution 1

So great, then a solution would be to not use navigation query parameters, when navigating to your MainPage. You can use variables on your MainViewModel to change the behavior as you like.

protectedoverridevoid OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (App.ViewModel.DoSomething) { App.ViewModel.DoSomething = false; DoSomething(); } }

**Problem 2**

You’d think this would’ve solved the issue and I could go to bed feeling good about myself. However, I was sorely mistaken. The constructor was still being called twice. Then it hit me, it wasn’t only a query parameter included in to the navigation string, but also the exact formatting of the navigation string.

The culprit in this case was WMAppManifest.xml. The NavigationPage was defined as shown, below:

<DefaultTask Name="_default" NavigationPage="ViewsMainPage.xaml" />

However, in my code, I was calling it like “/Views/MainPage.xaml”. For some reason Silverlight thinks “/Views/MainPage.xaml” and “/ViewsMainPage.xaml” are different, so that’s why it was creating a separate instance of MainPage.

Solution 2

Watch out how you format that navigation string and be consistent.