Operaciones básicas de programación con Metro y Windows 8 (VII) - Jorge Serrano - MVP Visual Developer - Visual Basic

Operaciones básicas de programación con Metro y Windows 8 (VII)

Navegación entre páginas de una aplicación – Avanzado

Parte I

Parte II

Parte III

 

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.

Published 29/6/2012 20:15 por Jorge Serrano
Comparte este post:

Comentarios

Saturday, June 30, 2012 4:48 PM por Jorge Serrano - MVP Visual Developer - Visual Basic

# Operaciones básicas de programación con Metro y Windows 8 (VIII)

Trabajando con ficheros de recursos e idiomas Parte II Parte III Parte IV   Trabajando con ficheros