Tags

, , ,

NavegandoEntrePáginas

Vamos ampliar un poco más la serie de post referentes a Descubriendo Windows Phone 8, tras realizar nuestra primera aplicación en el pasado post, vamos ahora a ver como es la navegación entre las distintas páginas y como podemos pasar parámetros de una a otra.

Todo aquel que ya haya implementado la navegación entre páginas en alguna de las versiones anteriores de Windows Phone verá que es exactamente lo mismo.

En Windows Phone las aplicaciones se componen con páginas. Podemos movernos de una a otra medainte el servicio de navegación incluido en el framework.

Vamos a crear una aplicación que contenga 2 páginas, pageOne, pageTwo. Algo sencillo, un botón en pageOne para navegar a pageTwo y otro en pageTwo para navegar a pageOne (aunque también podamos usar el botón del teléfono back). El XAML de pageOne quedaría de la siguiente forma:

  1. <Grid x:Name="LayoutRoot" Background="Transparent">
  2.         
  3.     <!–TitlePanel contains the name of the application and page title–>
  4.     <StackPanel x:Name="TitlePanel">
  5.         <TextBlock Text="MVPWAY.WORDPRESS.COM"
  6.                     Style="{StaticResource PhoneTextNormalStyle}"/>
  7.         <TextBlock Text="PAGE ONE" Style="{StaticResource PhoneTextTitle1Style}"/>
  8.     </StackPanel>
  9.  
  10.     <!–ContentPanel – place additional content here–>
  11.     <Grid x:Name="ContentPanel">
  12.         <Button Content="Ir a pageTwo"
  13.                 Click="Button_PageTwo"
  14.                 VerticalAlignment="Bottom"/>
  15.     </Grid>
  16. </Grid>

Para poder navegar desde pageOne a pageTwo al hacer clic en el botón solo tenemos que usar el método Navigate del NavigationService:

  1. private void Button_PageTwo(object sender, RoutedEventArgs e)
  2. {
  3.     NavigationService.Navigate(new Uri("/pageTwo.xaml",
  4.                                         UriKind.Relative));
  5. }

El caso de la pageTwo es muy parecido, solo debemos cambiar el Content del botón por “Ir a pageOne” y el evento de Click pondremos “/pageOne.xaml”.

El resultado de este pequeño ejemplo lo podéis descargar a continuación.

Descargar_Ejemplo

Paso de parámetros en la navegación

Una vez que hemos entendido como es la navegación entre páginas, algo bastante sencillo una vez visto, lo primero que se nos pasa por la cabeza es la necesidad de mandar información entre páginas. Nos encontramos con dos posibilidades, si los parámetros a pasar son valores simples, cadenas, números, booleanos. O por el contrario queremos enviar valores complejos como listas, objetos, etc.

Parámetros simples

Una de las características del servicio de navegación es la posibilidad de pasar parámetros de la misma forma que lo haríamos en una dirección web, mediante la Url. Vamos a modificar un poco nuestro ejemplo, creemos un TextBlock con el texto Nombre y un TextBox para poder recibir el valor a través del teclado.

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="*"/>
  5.     </Grid.RowDefinitions>
  6.     <Grid.ColumnDefinitions>
  7.         <ColumnDefinition Width="Auto"/>
  8.         <ColumnDefinition Width="*"/>                
  9.     </Grid.ColumnDefinitions>
  10.     <TextBlock Text="Nombre" Grid.Column="0"
  11.                 VerticalAlignment="Center"/>
  12.     <TextBox Name="txtNombre" Grid.Column="1"/>
  13.     <Button Content="Enviar datos" Grid.Row="1" Grid.Column="1"
  14.             Click="Button_Enviar_Datos" VerticalAlignment="Bottom"/>
  15. </Grid>

Y ahora nuestro evento Click va a reflejar la idea que hemos comentado, pasando el parámetro a través de la Uri.

  1. private void Button_Enviar_Datos(object sender, RoutedEventArgs e)
  2. {
  3.     string parameters = string.Format("?Nombre={0}", txtNombre.Text);
  4.  
  5.     NavigationService.Navigate(new Uri(
  6.         string.Format("/PageDats.xaml{0}", parameters),
  7.         UriKind.Relative));
  8. }

Para comprobar que realmente recibimos la información vamos a crearnos dos TextBlock.

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="*"/>
  5.     </Grid.RowDefinitions>
  6.     <Grid.ColumnDefinitions>
  7.         <ColumnDefinition Width="Auto"/>
  8.         <ColumnDefinition Width="*"/>
  9.     </Grid.ColumnDefinitions>
  10.     <TextBlock Text="Nombre" Grid.Column="0" FontSize="30"
  11.                 VerticalAlignment="Center"/>
  12.     <TextBlock Name="txtNombre" FontSize="18" Grid.Column="1"/>
  13. </Grid>

Para poder recuperar el valor que hemos pasado a la página mediante la URL, deberemos usar el objeto NavigationContext, que contiene una propiedad QueryString donde encontraremos todos los parámetros que hayamos incluido en nuestra URL. Desde el método OnNavigatedTo (este método es llamado cuando una página se convierte en la página activa de nuestra aplicación).

  1. protected override void OnNavigatedTo(NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedTo(e);
  4.     txtNombre.Text =
  5.         NavigationContext.QueryString["Nombre"].ToString();
  6. }

Si ejecutamos este breve código veremos que podemos escribir un texto y pasarlo a la segunda página de forma fácil y rápida.

Parámetros complejos

El problema es que la mayoría de las veces, la mayoría de nuestros proyectos necesitan pasar información de tipo complejo; clases, estructuras, listas, etc. Para este tipo de casos el paso de parámetros mediante la URL es demasiado engorroso. Por eso disponemos de una propiedad que nos facilitara esta tarea. La propiedad Content de los métodos OnNavigatedTo y OnNavigatedFrom (cuando la página activa hasta el momento deja de serlo).

Vamos a verlo en un ejemplo que es la manera más fácil de entender como funciona. Antes de nada añadimos a nuestro ejemplo unos cuantos campos más:

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="Auto"/>
  5.         <RowDefinition Height="Auto"/>
  6.         <RowDefinition Height="Auto"/>
  7.         <RowDefinition Height="*"/>
  8.     </Grid.RowDefinitions>
  9.     <Grid.ColumnDefinitions>
  10.         <ColumnDefinition Width="Auto"/>
  11.         <ColumnDefinition Width="*"/>
  12.     </Grid.ColumnDefinitions>
  13.     <TextBlock Text="Nombre" Grid.Column="0"
  14.                 VerticalAlignment="Center"/>
  15.     <TextBox Name="txtNombre" Grid.Column="1"/>
  16.     <TextBlock Text="Apellidos" Grid.Row="1" Grid.Column="0"
  17.                 VerticalAlignment="Center"/>
  18.     <TextBox Name="txtApellidos" Grid.Row="1" Grid.Column="1"/>
  19.     <TextBlock Text="Direccion" Grid.Row="2" Grid.Column="0"
  20.                 VerticalAlignment="Center"/>
  21.     <TextBox Name="txtDireccion" Grid.Row="2" Grid.Column="1"/>
  22.     <TextBlock Text="Telefono" Grid.Row="3" Grid.Column="0"
  23.                 VerticalAlignment="Center"/>
  24.     <TextBox Name="txtTelefono" Grid.Row="3" Grid.Column="1"/>
  25.     <Button Content="Enviar datos" Grid.Row="4" Grid.Column="1"
  26.             Click="Button_Enviar_Datos" VerticalAlignment="Bottom"/>
  27. </Grid>

Y hacemos lo necesario para representarlo en nuestra página de datos.

Una vez hecho lo referente a la interfaz de usuario, vamos a crearnos una clase (por ejemplo, persona) que recoja la información.

  1. public class Persona
  2. {
  3.     public string Nombre { get; set; }
  4.     public string Apellidos { get; set; }
  5.     public string Direccion { get; set; }
  6.     public string Telefono { get; set; }
  7.  
  8.     public Persona()
  9.     {
  10.     }
  11. }

Una vez lleguemos a este punto, vamos a realizar el Enlace a Datos en nuestras variables TextBox.

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="Auto"/>
  5.         <RowDefinition Height="Auto"/>
  6.         <RowDefinition Height="Auto"/>
  7.         <RowDefinition Height="*"/>
  8.     </Grid.RowDefinitions>
  9.     <Grid.ColumnDefinitions>
  10.         <ColumnDefinition Width="Auto"/>
  11.         <ColumnDefinition Width="*"/>
  12.     </Grid.ColumnDefinitions>
  13.     <TextBlock Text="Nombre" Grid.Column="0"
  14.                 VerticalAlignment="Center"/>
  15.     <TextBox Text="{Binding Nombre, Mode=TwoWay}" Grid.Column="1"/>
  16.     <TextBlock Text="Apellidos" Grid.Row="1" Grid.Column="0"
  17.                 VerticalAlignment="Center"/>
  18.     <TextBox Text="{Binding Apellidos, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"/>
  19.     <TextBlock Text="Direccion" Grid.Row="2" Grid.Column="0"
  20.                 VerticalAlignment="Center"/>
  21.     <TextBox Text="{Binding Direccion, Mode=TwoWay}" Grid.Row="2" Grid.Column="1"/>
  22.     <TextBlock Text="Telefono" Grid.Row="3" Grid.Column="0"
  23.                 VerticalAlignment="Center"/>
  24.     <TextBox Text="{Binding Telefono, Mode=TwoWay}" Grid.Row="3" Grid.Column="1"/>
  25.     <Button Content="Enviar datos" Grid.Row="4" Grid.Column="1"
  26.             Click="Button_Enviar_Datos" VerticalAlignment="Bottom"/>
  27. </Grid>

En la segunda página también utilizaremos el Enlace a Datos para mostrar la información recibida de la primera página.

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="Auto"/>
  5.         <RowDefinition Height="Auto"/>
  6.         <RowDefinition Height="Auto"/>
  7.         <RowDefinition Height="Auto"/>
  8.     </Grid.RowDefinitions>
  9.     <Grid.ColumnDefinitions>
  10.         <ColumnDefinition Width="Auto"/>
  11.         <ColumnDefinition Width="*"/>
  12.     </Grid.ColumnDefinitions>
  13.     <TextBlock Text="Nombre" Grid.Column="0" FontSize="30"
  14.                 VerticalAlignment="Center"/>
  15.     <TextBlock Text="{Binding Nombre}" FontSize="18" Grid.Column="1"/>
  16.     <TextBlock Text="Apellidos" Grid.Row="1" Grid.Column="0"
  17.                 FontSize="30" VerticalAlignment="Center"/>
  18.     <TextBlock Text="{Binding Apellidos}" FontSize="18"
  19.                 Grid.Row="1" Grid.Column="1"/>
  20.     <TextBlock Text="Direccion" Grid.Row="2" Grid.Column="0"
  21.                 FontSize="30" VerticalAlignment="Center"/>
  22.     <TextBlock Text="{Binding Direccion}" FontSize="18"
  23.                 Grid.Row="2" Grid.Column="1"/>
  24.     <TextBlock Text="Telefono" Grid.Row="3" Grid.Column="0"
  25.                 FontSize="30" VerticalAlignment="Center"/>
  26.     <TextBlock Text="{Binding Telefono}" FontSize="18"
  27.                 Grid.Row="3" Grid.Column="1"/>
  28. </Grid>

La navegación del botón que envía los datos a la segunda página será exactamente igual que cuando vimos como navegar de una página a otra sin necesidad de pasar parámetros.

Por último, vamos a enlazar ambas páginas. Crearemos una propiedad pública de tipo Persona que usaremos para recibir la información de la página principal, y que estableceremos como el DataContext de la página.

Después sobrescribiremos el método OnNavigatedFrom de nuestra página principal.

  1. protected override void OnNavigatedFrom(NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedFrom(e);
  4.  
  5.     PageDats pageDats = e.Content as PageDats;    
  6.     pageDats.DatosAMostrar = NuevaPersona;
  7.  
  8.     pageDats.DataContext = pageDats.DatosAMostrar;
  9. }

Ya tenemos nuestra navegación entre páginas y paso de parámetros complejos.

Os dejo los ejemplos que hemos visto de paso de parámetros.

Descargar_Ejemplo

Más información | Navegación con Windows Phone: conceptos básicos