Thursday, August 25, 2011

Passing Data between Pages in Windows Phone 7


Passing data among pages is something which needs to be given a little care in terms what approach you follow . Since each approach has its own benefits and side effects. I'll try to explain each of them one by one.

For illustration of this concept I've created a sample code which is attached at the end of the article. In this project I've various project each corresponds to one approach which I've described below. Each project has two pages. Touching on the coloured part of one page takes you to another page. First page will display a text string which is provided by the second page. You can simply go to second page add some text into TextBox and you can touch the coloured part to go back to first page which displays the string which you entered on first page.

So here are the approaches one by one:

1. Using Global Variable: This is the easiest and quickest procedure to pass your data among various pages.

Define a "Global Variable" in your App.xaml file as:
public string SecondPageText { get; set; }

After that on your Second page on ManipulationStarted event for the coloured Border use this code:
App.Current as App).SecondPageText = txtBox.Text; // add value to Global variable
NavigationService.GoBack(); // Navigate to first page

PhonePageOne page add this:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
     base.OnNavigatedTo(e);
     txtBlock.Text = (App.Current as App).SecondPageText;
}

2. Using Query String: This procedure is good when we just need to share string based data between two pages.

Add this code in your PhonePageTwo:
private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
         string uri = "/PhonePageOne.xaml?Text=";
         uri += txtBox.Text;
         NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}

Use this code in your PhonePageTwo:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
  base.OnNavigatedTo(e);
         IDictionary<string, string> parameters = this.NavigationContext.QueryString;
         if (parameters.ContainsKey("Text"))
         {
             txtBlock.Text = parameters["Text"];
         }
}

3. Using PhoneApplicationSerivce States: Every application has a PhoneApplicationService defined Microsoft.Phone.Shell. Each application has one PhoneApplicationService defined in its App.xaml file. We can use this service's property called "State". These "States" are all transient data which means they are available only for one instant of your application which means once you restart your application these states will be lost. Also we should not try to create a new PhoneApplicationService instead we must try to use the service from the current instant. Which can be retrieved using this code:

PhoneApplicationService.Current.State

Now, lets look how can we really use it in our sample.

PhonePageTwo add this code:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    PhoneApplicationService.Current.State["Text"] = txtBox.Text;
} 
private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
    NavigationService.GoBack();
}

PhonePageOne add this code:

private void LayoutRoot_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
 NavigationService.Navigate(new Uri("/PhonePageTwo.xaml", UriKind.Relative));
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if(PhoneApplicationService.Current.State.ContainsKey("Text"))
        txtBlock.Text = (string)PhoneApplicationService.Current.State["Text"];
}

4. Using NextPage intance: Whenever we call "Navigate" using a "/PageOne.xaml" or "/PageTwo.xaml" the OnNavigatedFrom method in current page is called with event arguments with a  Uri property indicating other page and a Content property of type that page (Navigating to) . After that OnNavigatedTo of other page will be called with same arguments. So we have an opportunity to fix the set the value for next page prior to navigating to it. Just take a look at the sample code:

PageTwo add this code:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if (e.Content is PageOne)
    {
        (e.Content as PageOne).txtBlock.Text = txtBox.Text;
    }
} 
private void Border_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
    NavigationService.GoBack();
}

PageOne add this code: (Basically no need to do any thing just use this)

private void LayoutRoot_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
 NavigationService.Navigate(new Uri("/PageTwo.xaml", UriKind.Relative));
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
 base.OnNavigatedTo(e);
}


Source Cod

15 comments:

  1. ;--page X
    PhoneApplicationService.Current.State["someName"] = someValue;

    ;---another page--

    object obj;
    if (PhoneApplicationService.Current.State.TryGetValue("pict", out obj))
    {
    //int blah=(int)obj;
    textBox1.text=obj.ToString();


    }

    ReplyDelete
  2. Omg Anonymous is here !

    ReplyDelete
  3. if not wrong u can also pass thru constructor...

    ReplyDelete
    Replies
    1. Yeah that may be another possible alternative. Though I'vent tried it but it seems it is more closer to techniques 4 and 2 that I've mentioned. 1 and 3 has unique advantage i.e. you need not to set values every time since they are available throught the session.

      Delete
  4. But if we have two pages and only one of them has UI and xaml file. How do you then make navigation? It seems that all 4 methods need xaml files for both pages, or did I miss something?

    ReplyDelete
    Replies
    1. pages with no Xaml ? are you creating some dynamic page using code behind ? Which sounds little strange for me.

      Delete
  5. Thanx a lot for saving my time.

    I was searching for the solution for "Passing custom class object from one page to another", and i think i should go with declaring Global variable.

    Let me know your suggestions.

    ReplyDelete
    Replies
    1. Well, it depends how you want to use it. I may defer to use Global variable unless no other option is applicable. Since, it's a static variable and will remain in memory as long as application run. And memory is a critical thing for mobile platform :-) However, if it's a small object to pass then we can live with it :-) rest lies how and where exactly you are going to use it.

      Delete
  6. Hello, i had to change two textblocks from a different page, i did it using the global variable but when i started the first page i need to have default information and it doesnt have anything.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. how to pas image value between pages!! for example if we have two images in two pages how to call second page image from first page

    ReplyDelete
    Replies
    1. You can use either strategy 1 or 4 as defined above. For (1)Simply change your code in App.xaml as shown below, also change accordingly in other relevant places and you are done with it.

      public BitmapImage SecondPageText { get; set; }

      Delete
  9. hi..i want to ask...i want to sum or add data like page one i input 6 in textbox and i'm klik button next it means + , in page two i input 2 and i klik next it means = , so in page 3 result 8 in textbox..can u help me to use variable global? thx :)

    ReplyDelete
    Replies
    1. for your case simplified solution is:

      Page1: Button click event you set a GlobalVariable = Pag1Text.value

      Page2: Button click event you set GlobalVariable = GlobalVariable + Pag2Text.value

      ResultPage: OnNavigatedTo method you can use the textboxDisplayResult = GlobalVariable

      I am giving you the hint for your logic.. you can use the proper syntax to convert this logic.

      Delete