Passing a complex object to a page while navigating in a WP7 Silverlight application

I use the NavigationService Navigate method to go to other pages of my WP7 Silverlight application:

 NavigationService.Navigate(new Uri("/Somepage.xaml?val=dreas", UriKind.Relative)); 

From Somepage.xaml I then retrieve the query string parameters as follows:

 string val; NavigationContext.QueryString.TryGetValue("val", out val); 



I now need a way to pass a complex object using a similar method . How can I do this without having to serialize the object every time I need to transfer it to a new page?

+15
c # windows-phone-7 silverlight navigation
Jan 15 '11 at 7:10
source share
5 answers

This is a very complex problem, and there is no easy solution. There is no magic API that just works for any application to solve this problem.

The main problem with passing navigation data is Tombstoning . The only piece of data that is the default tombstone is the navigation URI. therefore, if you use the QueryString parameter, it will be automatically loaded using gambling and your code. Each time you manually transfer an instance of an object, you will have to manually perform a tombstone collection for that instance yourself.

So, if you go to "/CowDetails.xaml?ID=1", your page will probably have perfect gambling by simply typing the Querystring ID parameter. However, if you somehow provide the CowDetails page with the "new Cow () {ID = 1}", you will need to make sure that the burial and zombify this value yourself.

In addition, there is a synchronization problem . When you call NavigationService.Navigate, the page you are viewing does not yet have an actual instance. Therefore, even if you switch to FooPage and have FooData, there is no way to immediately connect FooPage to FooData. You will have to wait for the PhoneApplicationFrame.Navigated event to fire to provide FooPage using FooData.

How I usually deal with this problem:

  • BasePage base has Data type property
  • Have a NavigationHelper get the page URI and data: NavigationHelper.Navigate ("foo.xaml", fooData)
  • I have a NavigationHelper to register for the PhoneApplicationFrame.Navigated event, and if it is "foo.xaml", set BasePage.Data to FooData.
  • If BasePage uses JSON.Net for the tombstone and the zombifix BasePage.Data.
  • In BasePage, I have a virtual OnDataSet method that is called when the Data property is filled with either Zombification or Navigation. In this method, everything related to business data occurs.
+14
Jan 18 '11 at 19:48
source share

App.xaml.cs -> Application class, add a field / property to it. To access it, if it is static use:

 App.MyComplexObject 

Or if not staic

 (App.Current as App).MyComplexObject; 
+9
Jan 15 '11 at 19:46
source share

There is a very simple solution to solve this problem. Consider the following example. A Windows Phone application has the following two pages: Page1.xaml and Page2.xaml Let's say we move from Page1.xaml to Page2.xaml. The navigation cycle begins when you call the NavigationService.Navigate method

  • First OnNavigatingFrom Event Page1 fires
  • Then the Designer from Page2 is triggered
  • Then the OnNavigatedFrom event Page1 is fired with a link to the created page in EventArgs ( e.Content has an instantiated Page2 )
  • Finally OnNavigatedTo Event Page2 fires

So, we get a link to another page on the page where the navigation begins.

 public class PhoneApplicationBasePage : PhoneApplicationPage { private object navParam = null; protected object Parameter{get;private set;} //use this function to start the navigation and send the object that you want to pass //to the next page protected void Navigate(string url, object paramter = null) { navParam = paramter; this.NavigationService.Navigate(new Uri(url, UriKind.Relative)); } protected override void OnNavigatedFrom(NavigationEventArgs e) { //e.Content has the reference of the next created page if (e.Content is PhoneApplicationBasePage ) { PhoneApplicationBasePage page = e.Content as PhoneApplicationBasePage; if (page != null) { page.SendParameter(navParam); navParam=null;} } } private void SendParameter(object param) { if (this.Parameter == null) { this.Parameter = param; this.OnParameterReceived(); } } protected virtual void OnParameterReceived() { //Override this method in you page. and access the **Parameter** property that // has the object sent from previous page } } 

So, in our Page1.xaml.cs we just call Navigate("/Page2.xaml",myComplexObject) . And in Page2.xaml.cs we will override the OnParameterReceived method

  protected override void OnParameterReceived() { var myComplexObjext = this.Parameter; } 

And you can also handle tombstone problems with minor changes in PhoneApplicationBasePage

+5
Oct 31 '12 at 7:25
source share

The debatable decision, in any case, makes it temporary.

Create this under your applicationโ€™s namespace for any page you need.

 public static class VarsForPages { // Be sure to include public static. public static SomeClass SomeClassObject; public static List<string> SomeList = new List<string>(); public static string SomeData = "SomeValue"; } // The syntax for referencing the data VarsForPages.SomeClassObject; VarsForPages.SomeList; VarsForPages.SomeData; 

Now you can refer to SomeClassObject, SomeList, SomeData anywhere in the application.

Note. Like any global data, get tired of the many accesses and changes that can be made to global data. I say this because I once had an increase in the size of the list, but one of my pages in the application relied on the size of the list to make some difference, and this caused an error. Remember that data is global.

+1
Sep 11 '12 at 6:12
source share

I wish I answered the vjsrinath answer above; this is IMO the best way to do this. Thank you very much!

Most likely, this is the closest thing that I saw how the iOS model works, where from the first page you called performSegue (== NavigateTo). Then you get a callback called prepareForSegue, which allows you to set variables on the landing page, set a delegate (usually for yourself), something like this.

To transfer a complex object, it removes the missing transfer parameters in the URL.

As an obvious example, let's say I want to pass the version string of my application into the "About" field, which is in a separate project:

In the calling class:

 private void About_Click(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/Library;component/Pages/About.xaml", UriKind.Relative)); } protected override void OnNavigatedFrom(NavigationEventArgs e) { if (e.Content is About) { About page = e.Content as About; if (page != null) { page.VersionString = App.VersionText; } } base.OnNavigatedFrom(e); } 

In the About class:

 public partial class About : PhoneApplicationPage { public string VersionString { get; set; } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); versionTextBlock.Text = VersionString; } } 

This is a very simple example, but the property you are passing through can be any object, which makes it very powerful. Of course, it can include callbacks, such as "saveButtonPressed", etc., Therefore, the save processing can be performed in the calling class and not in the presented view, which is pretty red for the convenience of the code. eg.

 page.OnSaveButtonPressed = this.SaveButtonPressedHandler; // Pass object to save as parameter 
+1
Mar 20 '13 at 22:36
source share



All Articles