Navigation between Pages is the predominant application paradigm for Windows Phone apps, when you are not creating a panorama app. Very often you will want to pass data between the individual items, for instance when the user selects an item from a list and the application navigates to a detailed view of that item. There are several solutions to that problem:

  1. Define a variable in the static Application object.
  2. Use the query string (forward navigation only)
  3. Use PhoneApplicationService
  4. Use delegates

Number 1 is simple. You define the variable you want to pass in the App class definition in App.xaml.cs, like so:

public partial class App : Application
{

public String GridToLoad { get; set; }

In your own classes you first get a reference to the Application object. Then you can set and get the value of the variable as you like:

var app = Application.Current as App;
app.GridToLoad = “foo”;

Number 2 is easy but only possible with forward navigation. Usually you call NavigationService.Navigate(new Uri(“/NewPage.xaml”, UriKind.RelativeOrAbsolute)) where you can pass a query string as you do with a web page, that is you concatenate something like “?parameter=value” to the URI string. However, when the user navigates back, you usually call NavigationService.GoBack(), where you can’t pass any parameters.

What I do is use the OnNavigatedTo() handler of the MainPage to hook into the navigation back from another page. Unfortunately Silverlight on Windows Phone does not offer a journal as does WPF, so you can’t tell which page you are returning from. I kind of created my own journal by using an instance variable of the Application object as showed above. So before I navigate to another page, I set the variable app.lastPage to the XAML file name of the page I am navigating to. So in the OnNavigatedTo() I can check the origin and read my variables (that I save in Application as well) accordingly:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var app = Application.Current as App;
if (app.lastPage == “/Settings.xaml”) {
LoadStoredSettings();

The most structured, although most involved solution is to use delegates. In that case you declare a handler in another class that you instantiate in the calling class. Adding specific methods of the calling class to that handler will trigger their execution when the called class calls the defined event. I am using a special class for loading the game hiscores in WORTOMAT. In that file I have defined the delegates the loader class (and a class for representing an individual hiscore, but that’s optional).

namespace WORTOMAT
{
public delegate void HiscoresLoadedHandler(List<Hiscore> hiscores);
public delegate void HiscoresLoadedErrorHandler(String reason);

public class Hiscore
{

}

class HiscoresLoader
{
public event HiscoresLoadedHandler HiscoresLoaded;
public event HiscoresLoadedErrorHandler HiscoresLoadedError;

public void Load() {
bool OK = DoSomething();
if (OK) {
HiscoresLoaded(hiscores);
} else {
HiscoresLoadedError(“some error”);
}
}
}
}

In the MainPage class I define an instance variable that gets initialized with an instance of the Loader class:

public partial class MainPage : PhoneApplicationPage
{
HiscoresLoader HsLoader = new HiscoresLoader();


In the MainPage constructor I add my handlers to both events defined in the HiscoresLoader file:

HsLoader.HiscoresLoaded += new HiscoresLoadedHandler(ShowHiscores);
HsLoader.HiscoresLoadedError += new HiscoresLoadedErrorHandler(HiscoresLoadingError);

The remaining work is to implement the two methods that are added in these assignments as parameters and that must correspond to the signatures of the delegate definition. That means “ShowHiscores” must take a List<Hiscore> as a parameter, while “HiscoresLoadingError” takes a string.