Pasar un objeto complejo a una página mientras navegas en una aplicación WP7 Silverlight

He estado usando el método Navigate NavigationService para navegar a otras páginas en mi aplicación WP7 Silverlight:

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

Desde Somepage.xaml , luego recupero los parámetros de cadena de consulta de la siguiente manera:

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

Ahora necesito una manera de pasar un objeto complejo usando una manera similar . ¿Cómo puedo hacer esto sin tener que serializar el objeto cada vez que necesito pasarlo a una página nueva?

Este es un problema extremadamente complejo, y no hay una solución simple aquí. No hay una API mágica que funcione para cualquier aplicación que resuelva este problema.

El problema central con el paso de los datos de navegación es Tombstoning . La única pieza de datos que se descabeza de forma predeterminada es el URI de navegación. así que si está utilizando un parámetro QueryString, se detectará automáticamente mediante el tombstoning y su código. Sin embargo, cada vez que pases manualmente una instancia de un objeto, tendrás que hacer tombstoning manualmente para esa instancia.

Por lo tanto, si navega a “/CowDetails.xaml?ID=1”, su página probablemente tendrá un perfecto tumulto solo al seleccionar el parámetro ID Querystring. Sin embargo, si de alguna manera proporciona la página de CowDetails con una “vaca nueva () {ID = 1}”, tendrá que asegurarse de hacer un tombstone y zombificar este valor usted mismo.

Además, está el problema del tiempo . Mientras llamas a NavigationService.Navigate, la página que estás navegando tampoco tiene una instancia real todavía. Por lo tanto, aunque esté navegando a FooPage y tenga listo el FooData, no hay forma de conectar FooPage inmediatamente a FooData. Tendrá que esperar hasta que se dispare el evento PhoneApplicationFrame.Navigated para proporcionar FooPage con FooData.

La forma en que normalmente trato este problema es:

  1. Tener una BasePage con un tipo de objeto Propiedad de datos
  2. Haga que NavigationHelper obtenga el URI y los datos de la página: NavigationHelper.Navigate (“foo.xaml”, fooData)
  3. Haga que NavigationHelper se registre en el evento PhoneApplicationFrame.Navigated y, si es “foo.xaml”, establezca BasePage.Data en FooData.
  4. Haga que BasePage use JSON.Net en Tombstone y zombificate BasePage.Data.
  5. En BasePage, tengo un método virtual OnDataSet que se invoca una vez que la propiedad Datos se rellena con Zombificación o Navegación. En este método, todo lo que tiene que ver con los datos comerciales ocurre.

App.xaml.cs -> Clase de aplicación, agregue un campo / propiedad allí. Para acceder, si es uso estático:

 App.MyComplexObject 

O si no es staic

 (App.Current as App).MyComplexObject; 

Hay una solución muy simple para abordar este problema. Considere el siguiente ejemplo Una aplicación de teléfono para Windows tiene dos páginas siguientes, Página1.xaml y Página2.xaml Digamos desde Page1.xaml estamos navegando a Page2.xaml . El ciclo de navegación comienza cuando llamas a NavigationService.Navigate method

  1. Primer OnNavigatingFrom Evento de incendios de Página1
  2. Luego, el Constructor de incendios de Page2
  3. Entonces OnNavigatedFrom event of Page1 se activa con la referencia de la página creada en sus EventArgs ( e.Content tiene la instancia creada de Page2 )
  4. Finalmente OnNavigatedTo Evento de incendios de Page2

Así que estamos obteniendo la referencia de la otra página en la página donde comienza la navegación.

 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 } } 

Por lo tanto, en nuestra página 1.xaml.cs simplemente llamamos a Navigate("/Page2.xaml",myComplexObject) . Y en su Page2.xaml.cs anularemos el método OnParameterReceived

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

Y también es posible manejar problemas de desecho con pequeños ajustes en PhoneApplicationBasePage

La solución discutible, en todo caso, la convierte en temporal.

Cree esto debajo del espacio de nombre de su aplicación para la página que sea necesaria.

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

Ahora puede hacer referencia a SomeClassObject, SomeList, SomeData en cualquier lugar de la aplicación.

Nota: como cualquier dato global, esté cansado de los muchos accesos y modificaciones que se pueden hacer a los datos globales. Digo esto, porque una vez tuve un aumento en el tamaño de la lista, pero una de mis páginas en la aplicación dependía del tamaño de la lista para ser de algún valor, y esto causó un error. No lo olvides, los datos son globales.

Desearía poder responder a la respuesta de vjsrinath anterior; es IMO la mejor manera de hacer esto. ¡¡Muchas gracias!!

Es probablemente lo más parecido que he visto a la forma en que funciona el modelo de iOS, donde desde la primera página llamabas a performSegue (== NavigateTo). A continuación, obtiene una callback llamada prepareForSegue, que le permite configurar variables en la página de destino, establecer el delegado (generalmente en sí mismo), ese tipo de cosas.

Para pasar objetos complejos, supera a los pantalones que pasan los parámetros en la URL.

Como un ejemplo explícito, digamos que quiero pasar la cadena de versión de mi aplicación a un cuadro Acerca de que está en un proyecto separado:

En la clase de llamada:

 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); } 

En la clase Acerca de:

 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; } } 

Este es un ejemplo muy simple, por supuesto, pero la propiedad por la que está pasando podría ser cualquier objeto, lo que lo hace muy poderoso. Por supuesto, puede incluir devoluciones de llamadas como “saveButtonPressed”, etc. por lo que el manejo de guardado se puede realizar en la clase de llamada, no en la vista presentada, que es bastante mala para el orden del código. p.ej,

 page.OnSaveButtonPressed = this.SaveButtonPressedHandler; // Pass object to save as parameter