Operaciones básicas de programación con Metro y Windows 8 (VII)
Navegación entre páginas de una aplicación – Avanzado
Navegación entre páginas de una aplicación – Avanzado (IV)
Trabajando con OnNavigatedTo en la página principal
Cada vez que navegamos de una página a otra, el evento de la página a la que se navega que se lanza, es el evento OnNavigatedTo.
En nuestro ejemplo, tendremos un código similar al siguiente:
1: /// <summary>
2: /// Invoked when this page is about to be displayed in a Frame.
3: /// </summary>
4: /// <param name="e">
5: /// Event data that describes how this page was reached. The Parameter
6: /// property is typically used to configure the page.
7: /// </param>
8: protected override void OnNavigatedTo(NavigationEventArgs e)
9: {
10: if (e.NavigationMode == NavigationMode.Back)
11: {
12: // Cargamos el estado previo.
13: Planeta planeta = App.Current.Resources["Planeta"] as Planeta;
14: if (planeta != null)
15: {
16: MessageDialog messageDialog = new MessageDialog(String.Format(
17: "Ha seleccionado {0} con un diámetro
18: ecuatorial de {1} kilómetros.",
19: planeta.Nombre,
20: planeta.Diametro));
21: messageDialog.ShowAsync();
22: // Mostramos la imagen.
23: var uri = new Uri("ms-appx:///" + planeta.RutaImagen);
24: this.imgPlaneta.Source = new BitmapImage(uri);
25: this.tbNombrePlaneta.Text = planeta.Nombre;
26: this.tbDiametroPlaneta.Text = String.Format("{0} kilómetros", planeta.Diametro);
27: }
28: }
29: } // OnNavigatedTo
De acuerdo al código anterior, observamos varias cosas.
Al principio del todo, podemos preguntar si estamos regresando a la página principal desde otra página o no.
Esto lo logramos con este código:
1: if (e.NavigationMode == NavigationMode.Back)
2: {
3: }
Nota: Recordemos, que en Metro, nosotros debemos crear y gestionar el flujo de navegación de nuestra aplicación.
Una vez dentro de esta cláusula if, podemos realizar la operación u operaciones que consideremos oportunas.
En nuestro caso, he querido obtener el planeta seleccionado, sin embargo, aquí estoy obligado a hacer un alto en el camino.
Alto en el camino que hago por haberme tomado la libertad de gestionar el almacenamiento del planeta seleccionado dentro de la aplicación de una manera particular.
He pensado en este ejemplo, compartir el recurso planeta utilizando la clase App.
El funcionamiento es muy sencillo, basta con utilizar App.Current.Resources[key] para indicar al recurso el valor del mismo o para recuperarlo.
En MainPage.xaml estamos recuperando ese valor, y en BasicPage1.xaml lo asignaremos como veremos más adelante.
Es por eso que en nuestro ejemplo, recuperamos el valor de la clase Planeta de esta forma:
1: Planeta planeta = App.Current.Resources["Planeta"] as Planeta;
Finalmente y para asegurarnos de que posee un valor válido, preguntamos si planeta es nulo o no.
En el caso de que no sea nulo, mostramos un mensaje en pantalla indicando los detalles del planeta seleccionado, y acto seguido, mostramos esos mismos datos en la página junto a la imagen del planeta seleccionado.
Un detalle a tener en cuenta es la carga de una imagen en Metro.
Como podemos apreciar, la instrucción de carga que hemos utilizado es de la siguiente forma:
1: var uri = new Uri("ms-appx:///" + planeta.RutaImagen);
2: this.imgPlaneta.Source = new BitmapImage(uri);
Existen dos maneras de cargar una imagen, a través de ms.appx:///ruta_imagen, o a través de la ruta ms-appdata:///ruta_imagen.
Finalmente, vamos a ver como se comporta BasicPage1.xaml para que podamos jugar con los datos que devuelve hacia MainPage.xaml.
Programando la página secundaria BasicPage1.xaml
El código fuente de esta página secundaria quedará de la siguiente manera:
1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Linq;
5: using Windows.Foundation;
6: using Windows.Foundation.Collections;
7: using Windows.UI.Xaml;
8: using Windows.UI.Xaml.Controls;
9: using Windows.UI.Xaml.Controls.Primitives;
10: using Windows.UI.Xaml.Data;
11: using Windows.UI.Xaml.Input;
12: using Windows.UI.Xaml.Media;
13: using Windows.UI.Xaml.Navigation;
14:
15: namespace Sample2
16: {
17:
18: /// <summary>
19: /// A basic page that provides characteristics common to most applications.
20: /// </summary>
21: public sealed partial class BasicPage1 : Sample2.Common.LayoutAwarePage
22: {
23:
24: /// <summary>
25: /// Constructor de la clase.
26: /// </summary>
27: public BasicPage1()
28: {
29: this.InitializeComponent();
30: // Habilitamos la caché.
31: this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
32: // Cargamos los datos en el control comboBox.
33: LoadPlanetas();
34: } // BasicPage1 Constructor
35:
36: /// <summary>
37: /// Variable privada encargada de almacenar
38: /// los datos del planeta seleccionado.
39: /// </summary>
40: public Planeta planeta;
41:
42: /// <summary>
43: /// Populates the page with content passed during navigation. Any saved state is also
44: /// provided when recreating a page from a prior session.
45: /// </summary>
46: /// <param name="navigationParameter">The parameter value passed to
47: /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
48: /// </param>
49: /// <param name="pageState">A dictionary of state preserved by this page during an earlier
50: /// session. This will be null the first time a page is visited.</param>
51: protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
52: {
53: } // LoadState
54:
55: /// <summary>
56: /// Preserves state associated with this page in case the application is suspended or the
57: /// page is discarded from the navigation cache. Values must conform to the serialization
58: /// requirements of <see cref="SuspensionManager.SessionState"/>.
59: /// </summary>
60: /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
61: protected override void SaveState(Dictionary<String, Object> pageState)
62: {
63: } // SaveState
64:
65: /// <summary>
66: /// Método encargado de cargar el listado de
67: /// los planetas del Sistema Solar.
68: /// </summary>
69: private void LoadPlanetas()
70: {
71: SistemaSolar sistemaSolar = new SistemaSolar();
72: List<Planeta> planetas = sistemaSolar.GetPlanetas();
73: this.cboPlanetas.ItemsSource = planetas;
74: this.cboPlanetas.DisplayMemberPath = "Nombre";
75: this.cboPlanetas.SelectedValuePath = "Id";
76: this.cboPlanetas.SelectedIndex = 0;
77: } // LoadPlanetas
78:
79: /// <summary>
80: /// Evento que se lanza al seleccionar un planeta de la lista de planetas.
81: /// </summary>
82: /// <param name="sender"></param>
83: /// <param name="e"></param>
84: private void cboPlanetas_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
85: {
86: this.planeta = (Planeta)(this.cboPlanetas.SelectedItem);
87: } // cboPlanetas_SelectionChanged_1
88:
89: /// <summary>
90: /// Evento que ejecutamos al dejar la página.
91: /// </summary>
92: /// <param name="e"></param>
93: protected override void OnNavigatedFrom(NavigationEventArgs e)
94: {
95: // En nuestro ejemplo, sólo tenemos 1 elemento en los recursos,
96: // por lo que la validación es muy sencilla.
97: // Basta con ver si hay algún recurso o no creado.
98: // Si no lo hay, lo creamos, y en caso contrario, lo reutilizamos.
99: if (App.Current.Resources.Count() == 0)
100: {
101: App.Current.Resources.Add(
102: "Planeta",
103: this.planeta);
104: }
105: else
106: {
107: App.Current.Resources["Planeta"] = this.planeta;
108: }
109: } // OnNavigatedFrom
110:
111: } // BasicPage1
112:
113: } // Sample2
Atendiendo al código de esta página secundaria, observamos que en el constructor, hemos habilitado la caché y hemos llamado a un método que se encargará de cargar los planetas y sus datos (tómese como un ejemplo demo).
1: /// <summary>
2: /// Constructor de la clase.
3: /// </summary>
4: public BasicPage1()
5: {
6: this.InitializeComponent();
7: // Habilitamos la caché.
8: this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
9: // Cargamos los datos en el control comboBox.
10: LoadPlanetas();
11: } // BasicPage1 Constructor
Nuestra función de carga de los planetas y la carga de todos estos datos en el control ComboBox de la página BasicPage1.xaml queda de la siguiente manera:
1: /// <summary>
2: /// Método encargado de cargar el listado de
3: /// los planetas del Sistema Solar.
4: /// </summary>
5: private void LoadPlanetas()
6: {
7: SistemaSolar sistemaSolar = new SistemaSolar();
8: List<Planeta> planetas = sistemaSolar.GetPlanetas();
9: this.cboPlanetas.ItemsSource = planetas;
10: this.cboPlanetas.DisplayMemberPath = "Nombre";
11: this.cboPlanetas.SelectedValuePath = "Id";
12: this.cboPlanetas.SelectedIndex = 0;
13: } // LoadPlanetas
De igual manera, hemos declarado una variable para trabajar con el planeta seleccionado:
1: /// <summary>
2: /// Variable privada encargada de almacenar
3: /// los datos del planeta seleccionado.
4: /// </summary>
5: public Planeta planeta;
Evidentemente, cada vez que modificamos la selección de un planeta, damos cuenta de ellos:
1: /// <summary>
2: /// Evento que se lanza al seleccionar un planeta de la lista de planetas.
3: /// </summary>
4: /// <param name="sender"></param>
5: /// <param name="e"></param>
6: private void cboPlanetas_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
7: {
8: this.planeta = (Planeta)(this.cboPlanetas.SelectedItem);
9: } // cboPlanetas_SelectionChanged_1
Para finalizar, al igual que en la página principal trabajábamos con el evento OnNavigatedTo, aquí trabajaremos con el evento OnNavigatedFrom.
Este evento será utilizado cada vez que dejemos la página en la que estamos.
Podemos utilizar este evento para muchísimos fines, y uno de ellos según lo he querido yo aquí, para guardar el recurso del planeta seleccionado:
1: /// <summary>
2: /// Evento que ejecutamos al dejar la página.
3: /// </summary>
4: /// <param name="e"></param>
5: protected override void OnNavigatedFrom(NavigationEventArgs e)
6: {
7: // En nuestro ejemplo, sólo tenemos 1 elemento en los recursos,
8: // por lo que la validación es muy sencilla.
9: // Basta con ver si hay algún recurso o no creado.
10: // Si no lo hay, lo creamos, y en caso contrario, lo reutilizamos.
11: if (App.Current.Resources.Count() == 0)
12: {
13: App.Current.Resources.Add(
14: "Planeta",
15: this.planeta);
16: }
17: else
18: {
19: App.Current.Resources["Planeta"] = this.planeta;
20: }
21: } // OnNavigatedFrom
En este caso, no he querido llamar al método Contains ni a ningún otro método o función para saber si ya hay recursos guardados.
En esta aplicación sólo voy a tener un solo recurso, por lo que simplemente pregunto cuantos hay, y si hay 0, es que el usuario ha accedido a esta página por primera vez, y si hay uno, entonces simplemente sobreescribo el recurso de clave o key «Planeta» con el objeto Planeta seleccionado del control ComboBox.
Nuestra aplicación en ejecución es tal y como se indican en las dos siguientes capturas:
El resultado una vez cerrada la ventana de mensaje de diálogo es de esta manera:
En próximas entradas, espero podamos ver otras cosas diferentes relacionadas con la programación Metro.
One Responseso far
Trabajando con ficheros de recursos e idiomas Parte II Parte III Parte IV Trabajando con ficheros