Windows Phone 8. Introducción al control LongListSelector.

Un viejo conocido

Si en Windows Phone entramos al Hub People podemos ver que para acceder a un contacto de nuestro listado disponemos aparte de hacer scroll como en una lista común, de una serie de cuadrados con la letra inicial de los nombres que vienen a continuación.

Si pulsamos en uno de esos cuadrados aparece un listado con todas las letras del abecedario. Si seleccionamos uno de esos cuadrados nos posiciona en la sección que comienza por la letra que hemos pulsado.

LongListSelector

LongListSelector

Es ideal para interfaces que van a mostrar una gran colección de elementos. Facilitamos al usuario el acceso directo a la zona que desea.

Para quienes hayan probado el Toolkit de Windows Phone, el control LongListSelector les será un viejo conocido. Efectivamente el control estaba previamente incorporado dentro del conjunto del controles del Toolkit. Ahora, en Windows Phone 8, lo tenemos incluido dentro del propio SDK.

En este artículo vamos a analizar las posibilidades del control, ¿comenzamos?

RECUERDA: El control LongListSelector es como un control ListBox avanzado que puede mostrar dos listas, una  plana y otra agrupada. Ayuda a los usuarios a navegar a través de largas listas, le permite saltar entre las diferentes secciones de la lista mediante una rejilla que se superpone a la lista cuando el usuario selecciona uno de los encabezados.

NOTA: El LongListSelector incluido en el SDK de Windows Phone 8 es diferente al ya conocido LongListSelector  del Windows Phone Toolkit. Aunque a simple vista pueden parecer similares, el nuevo control expone propiedades diferentes y se utiliza de una manera ligeramente diferente.

Manos a la obra

Creamos un nuevo proyecto:

Aplicación Windows Phone

Aplicación Windows Phone

Para probar el control necesitamos una fuente de información. En nuestro ejemplo simplificaremos el proceso al máximo construyendo una colección de elementos en memoria. Vamos a mostrar una colección de teléfonos agrupados por sistema operativo. Comenzamos creando la estructura de la información a mostrar. Creamos una carpeta Models. Dentro de la carpeta vamos a crear una clase Telephone.cs:

public class Telehpone
{
    public string Name
     {
          get;
          set;
     }

     public string OS
     {
          get;
          set;
     }
}

Creamos una carpeta ViewModels donde añadimos una nueva clase llamada MainPageViewModel.cs:

public MainPageViewModel()
{

}

Necesitamos una colección de elementos para abastecer al control LongListSelector:

private List<Telehpone> _telephones;

En el constructor del ViewModel vamos a crear la colección de elementos a mostrar:

public MainPageViewModel()
{
     _telephones = new List<Telehpone>();
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 700", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 800", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 620", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 820", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 920", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC Titan", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC 8S", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC 8X", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S2", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S3", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Sony Xperia S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Sony Xperia U", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC Desire", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC One S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC One X", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC Sensation XL", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "iPhone 4", OS = "IOS" });
     _telephones.Add(new Telehpone() { Name = "iPhone 4S", OS = "IOS" });
     _telephones.Add(new Telehpone() { Name = "iPhone 5", OS = "IOS" });
}

Nuestro objetivo es mostrar la información agrupada por sistema operativo. De esta forma el usuario podrá pulsar sobre las cabeceras del LongListSelector (los distintos sistemas operativos móviles, los grupos) y así poder acceder al conjunto de elementos pertenecientes a un grupo de manera rápida y efectiva. Para ello, vamos a crear una pequeña clase que nos permita agrupar la información:

public class Group<T> : List<T>
{
     public Group(string name, IEnumerable<T> items)
     : base(items)
     {
          this.OS = name;
     }

     public string OS
     {
          get;
          set;
     }
}

La clase Group nos permitirá almacenar en una lista los teléfonos de un mismo sistema operativo.

NOTA: La clase es genérica con el objetivo de poder reutilizarla con otros tipos de datos.

LongListSelector Structure 1

Continuamos contruyendo la interfaz de usuario. Nos centramos en el archivo MainPage.xaml.

Vamos a definir las distintas plantillas que debemos utilizar en el LongListSelector y que ya hemos analizado previamente. Comenzamos con la plantilla GroupHeaderTemplate que definirá el aspecto de las cabeceras de cada grupo:

<DataTemplate x:Key="TelephoneGroupHeaderTemplate">
     <Border Background="Transparent" Padding="5">
          <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="462"
          Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
               <TextBlock Text="{Binding OS}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="24" Padding="6"
               FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
          </Border>
     </Border>
</DataTemplate>

La siguiente plantilla, ItemTemplate, define el aspecto de cada elemento de la lista:

<DataTemplate x:Key="TelephoneItemTemplate">
     <Grid>
          <TextBlock Text="{Binding Name}"/>
     </Grid>
</DataTemplate>

Podemos definir ya el control LongListSelector:

<phone:LongListSelector x:Name="longListSelector"
     Background="Transparent"
     IsGroupingEnabled="True"
     LayoutMode="List"
     ItemsSource="{Binding TelephonesGrouped}"
     GroupHeaderTemplate="{StaticResource TelephoneGroupHeaderTemplate}"
     ItemTemplate="{StaticResource TelephoneItemTemplate}"/>

Si compilamos y probamos podemos observar que algo no va bien… ¿que ocurre?

Al pulsar sobre una de las cabeceras no ocurre nada. Debería de superponerse una rejilla con cada uno de los grupos de modo que permitan posicionar al usuario al inicio del grupo en la lista plana.

¿Cómo lo solucionamos?

Utilizamos la propiedad JumpListStyle para ello. Con esta propiedad indicaremos como se comporta el LongListSelector al pulsar cabeceras.

NOTA: Si no definimos la propiedad IsGroupingEnable a True la lista aparecería sin agrupar, al igual que veríamos en un ListBox.

Lo primero que haremos será utilizar dos Converters disponibles en el SDK para determinar fuente y fondo de cada grupo que aparecerá en la rejilla que superpones al pulsar una cabecera (si aparece pero con otro color o no, etc):

<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>

A continuación, definimos el estilo JumListStyle:

<Style x:Key="TelephoneJumpListStyle" TargetType="phone:LongListSelector">
     <Setter Property="GridCellSize"  Value="480,113"/>
     <Setter Property="LayoutMode" Value="Grid" />
     <Setter Property="ItemTemplate">
          <Setter.Value>
               <DataTemplate>
                    <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="480" Height="113" Margin="6">
                         <TextBlock Text="{Binding OS}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="24" Padding="6"
                         Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
                    </Border>
               </DataTemplate>
          </Setter.Value>
     </Setter>
</Style>

Se lo asignamos al LongListSelector:

JumpListStyle="{StaticResource TelephoneJumpListStyle}"

De modo que finalmente quedaría así:

<phone:LongListSelector x:Name="longListSelector"
     Background="Transparent"
     IsGroupingEnabled="True"
     LayoutMode="List"
     ItemsSource="{Binding TelephonesGrouped}"
     JumpListStyle="{StaticResource TelephoneJumpListStyle}"
     GroupHeaderTemplate="{StaticResource TelephoneGroupHeaderTemplate}"
     ItemTemplate="{StaticResource TelephoneItemTemplate}"/>

NOTA: El control LongListSelector está definido dentro del namespace “Microsoft.Phone.Controls”.

Si compilamos nuestro proyecto para probar debemos obtener el siguiente resultado:

Ejemplo LongListSelector 1

Vista con todos los elementos

Ejemplo LongListSelector 2

Vista grupos

Conclusiones

Puedes descargar el ejemplo realizado:

El control LongListSelector lo tenemos ahora disponible en el SDK de Windows Phone 8. Es un control sumamente versátil con múltiples opciones de agrupación. Además, soporta virtualización de datos y de interfaz de usuario por lo que se recomienda su uso incluso para mostrar listas planas de datos (tal como haríamos con un control ListBox).

Recordar, cualquier duda o sugerencia será bienvenida en los comentarios de la entrada.

Más información

9 pensamientos en “Windows Phone 8. Introducción al control LongListSelector.

    • Gracias Francisco Javier.
      Si tengo en mente un par de artículos sobre el control LongListSelector. Uno de los temas más interesantes es sin duda el trabajo con un volumen alto de información y el buen uso de la virtualización. Tomo nota😉

      Un saludo.

  1. Cuando defines el LongListSelector pones la propiedad ItemsSource como “Binding TelephonesGrouped” pero TelephonesGrouped no lo encuetro en ningun lado. He tratado de vincular mi LongListSelector con la fuente de informacion, pero no puedo, podrias ayudarme?

  2. Pingback: [Universal App] Uso del Zoom Semantico, creando Jumplists | Javier Suárez | Blog

  3. Pingback: [Universal App] Uso del Zoom Semantico, creando Jumplists - Javier Suárez

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