WinRT. GridView con elementos de tamaño variable.

Desde que está accesible el Windows Store en el Consumer Preview de Windows 8, personalmente creo que es una de las aplicaciones mejor diseñadas y a la vez más atractivas visualmente.

Muestra las aplicaciones organizadas por grupos. Además, según sea la aplicación más o menos destacada, ocupan un tamaño u otro.

En la entrada actual, veremos los pasos necesarios para realizar una interfaz similar.

Comenzamos recordando las plantillas básicas que tenemos disponibles para crear aplicaciones Metro Style. Son las siguientes:

  • Blank Application. Proyecto base más simple. Contamos con una simple página por defecto además de todos los recursos necesarios para la aplicación.
  • Split Application. Especialmente pensado para mostrar una lista de elementos junto a su vista de detalles. Muy utilizado en aplicaciones tipo gestor de correo, cliente rss, etc.

  • Grid Application. Si estás familiarizado con el desarrollo de Windows Phone y has utilizado el control panorama puede ayudarte a hacerte una idea. Mostramos un conjunto de elementos organizados en grupos. Nos movemos utilizando un scroll horizontal. Al pulsar sobre la cabecerá se redireccionará a una página donde se muestran los detalles de la colección. En caso de pulsar sobre un elemento de la colección se nos mostrará una página con los detalles del elemento seleccionado. Realizaremos múltiples ejemplos en próximas entradas donde trataremos con más detalle esta plantilla. Muy usado en aplicaciones de noticias, colecciones multimedias de fotos o videos, etc.

Grid Application

En esta entrada vamos a centrarnos en la plantilla “Grid Application”. Abrimos Visual Studio para crear un nuevo proyecto seleccionando la plantilla Grid Application. Al proyecto que tenemos disponible al final de la entrada se le ha llamado Ejemplo_GridView_Variable. Esta plantilla es muy interesante y completa. Nos permite crear una vista Master/Detail totalmente adaptada al uso táctil.

Antes de ejecutar el proyecto recien creado (pulsando F5) vamos a pararnos a analizar brevemente la arquitectura creada en el Explorador de soluciones.

Destacamos:

  • El contenido de la carpeta DataModel. Es la fuente de datos utilizada en la plantilla. Si estas familiarizado con el uso de MVVM en aplicaciones WPF, Silverlight o Windows Phone te resultará familiar la estructura del proyecto. En caso contrario, no te preocupes, en próximas entradas analizaremos detenidamente el patrón.
  • GroupedItemsPage. Es la primera de las vistas que visualizaremos al arrancar la aplicación. Aquí tenemos disponible el control GridView.
  • GroupDetailPage. Es la vista mostrada al seleccionar el título de un grupo.
  • ItemDetailPage. Nos muestra los detalles de un elemento en concreto. Dentro de esta vista se hace uso del control FlipView. Dicho control es sumamente interesante y lo analizaremos en futuras entradas.

Vista de manera rápida la estructura del proyecto vamos a ejecutarlo.

De entrada vemos la siguiente vista:

La vista anterior esta definida dentro del XAML GroupedItemsPage. El control principal es un GridView. Los datos que utilizamos en el GridView los tenemos establecidos dentro de una clase disponible en la carpeta DataModel.

Si seleccionamos la cabecera de alguno de los grupos veremos:

Nos muestra una vista detallada con todos los elementos del grupo. En el simil con respecto al Windows Store veríamos todas las aplicaciones de una categoría en concreto. Corresponde al XAML GroupDetailPage. Por último tenemos la siguiente vista:

Es la vista detallada de un elemento en concreto. Recurriendo al simil del Windows Store serían los detalles de una aplicación concreta. Corresponde al XAML ItemDetailPage.

Tras ver lo que nos ofrece la plantilla correspondiente al GridView podemos deducir que nos viene perfecta para simular la estructura del Windows Store. Sin embargo, tenemos un gran problema que solventar.

¿Que problema?

Sencillo. En nuestra aplicación, hasta ahora todos los elementos del GridView ocupan el mismo tamaño. En el Windows Store para dar más peso a ciertas aplicaciones destacadas se le asigna un tamaño superior.

¿Cómo lo conseguimos?

De manera similar a como en un Grid utilizamos las propiedades RowSpan y ColumnSpan. Es decir, ciertos elementos ocuparán más de una celda.

Para ello vamos a crear una clase personal que derivará del GridView:

public class GridViewVariableSize : GridView
{
}

Dentro de la clase que hemos creado vamos a sobrescribir el método PrepareContainerForItemOverride.

public class GridViewVariableSize : GridView
{
     protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
     {
          SampleDataItem sampleDataItem = item as SampleDataItem;
          if (sampleDataItem != null)
          {
               element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, sampleDataItem.ColumnSpan);
               element.SetValue(VariableSizedWrapGrid.RowSpanProperty, sampleDataItem.RowSpan);
          }

          base.PrepareContainerForItemOverride(element, item);
     }
}

El método PrepareContainerForItemOverride es el encargado de establecer los estilos y plantillas de cada elemento del GridView.

NOTA: En este ejemplo se están utilizando los objetos definidos en la fuente de datos de prueba creados por la plantilla de Visual Studio.

Necesitarás en la clase los siguientes using:

using Ejemplo_GridView_Variable.Data;
using Windows.UI.Xaml.Controls;

En la interfaz disponible en el XAML de GroupedItemsPage debemos sustituir el control GridView utilizado por el nuestro GridViewVariableSize.

Para asignar el número de columnas o filas que tendra cada item haremos lo siguiente (necesario para que lo sobrescrito en nuestro custom GridView funcione y no de error al compilar):

private int _rowSpan = 1;
public int RowSpan
{
     get { return _rowSpan; }
     set { _rowSpan = value; }
}

private int _columnSpan = 1;
public int ColumnSpan
{
     get { return _columnSpan; }
     set { _columnSpan = value; }
}

Hemos añadido dos propiedades (RowSpan y ColumnSpan) para poder definir el tamaño deseado en la representación visual de cada SampleDataItem. Por defecto, sin alterar las propiedades el valor es el normal, es decir, una fila y una columna.

Para modificar el tamaño de un elemento bastará con hacer lo siguiente (en el ejemplo se modifica el tamaño del segundo elemento del primero grupo):

var segundoElemento = new SampleDataItem("Group-1-Item-2",
"Item Title: 2",
"Item Subtitle: 2",
"Assets/LightGray.png",
"Item Description: Pellentesque porta, mauris quis interdum vehicula, urna sapien ultrices velit, nec venenatis dui odio in augue. Cras posuere, enim a cursus convallis, neque turpis malesuada erat, ut adipiscing neque tortor ac erat.",
ITEM_CONTENT,
group1);
segundoElemento.ColumnSpan = 3;
group1.Items.Add(segundoElemento);

Le hemos asignado al segundo elemento el tamaño correspondiente a 3 columnas. El resultado:

Esto… no es lo que esperabamos, ¿verdad?

¿Que ocurre?.

Fácil. Si vemos el ItemTemplate aplicado a cada elemento es Standard250x250ItemTemplate. Por el nombre ya sabemos que puede estar ocurriendo. A cada item se le asigna un tamaño fijo de 250x250px.

Lo solucionaremos creando un nuevo DataTemplate sin asignar tamaños fijos:

<DataTemplate x:Key="StandardItemTemplate">
     <Grid HorizontalAlignment="Left">
          <Border Background="{StaticResource ListViewItemPlaceholderRectBrush}">
               <Image Source="{Binding Image}" Stretch="UniformToFill"/>
          </Border>
          <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundBrush}">
               <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayTextBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
               <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryTextBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
          </StackPanel>
     </Grid>
</DataTemplate>

El resultado:

Si quieres hacer pruebas rápidamente tienes a continuación el ejemplo completo correspondiente a esta entrada:

Espero que lo visto en la entrada os sea de utilidad. Si surge alguna duda o sugerencia puedes dejarla en los comentarios de la entrada.

Más información:

Foros MSDN: How To: Create a Variable Sized Grouped GridView (like the store). En inglés. Similar a lo realizado en esta entrada. Se crean una serie de tamaños comunes por defecto. Interesante.

Lee´s Corner: Customizing GridView Items in Metro App. En ingles. Una solución también similar a la realizada aquí.

5 pensamientos en “WinRT. GridView con elementos de tamaño variable.

  1. Buen Día, Pregunto, si tengo el nombre de una imagen en una tabla de SQLite, como hago para mostrarlo en la plantilla Standard250x250ItemTemplate..

    • Hola Rafael,

      Me confirmas que utilizas SQLite. Me imagino que en la base de datos almacenas la ruta a la imagen que almacenas en el Storage file, ¿utilizas MVVM?. Si es asi, básicamente sería que el modelo obtenga el objeto deseado, el ViewModel prepara la imágen para la vista. Es decir, obtendría la imágen correspondiente dada la ruta almacenada y realizando binding la interfaz se comunicaría con el ViewModel.

      Si por el contrario quieres almacenar la imágen en la propia base de datos, puedes hacerlo convirtiendo la imagen a string (la imagen a array de bytes, y de array de bytes a string utilizando base64).

      Espero haberte ayudado. Con un poco más de información podría ayudarte mejor. La pregunta es interesante, la apunto para una futura entrada (Tips and Tricks).

      Un saludo.

  2. Pingback: Megathon microsoft | Interesting post related with controls in Xaml WinRt

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s