Windows phone. Introducción al control Listpicker.

Control Listpicker

El control Listpicker lo tenemos disponible dentro del Windows Phone Silverlight Toolkit, paquete de controles totalmente gratuito disponible tanto en Codeplex como utilizando Nuget. Ya hablamos de que como instalar y que contenía el Toolkit en la siguiente entrada:

Introducción al Windows Phone Silverlight Toolkit

El control ListPicker nos permite mostrar una serie de opciones a elegir por parte del usuario (de manera muy similar a como lo haríamos utilizando un ComboBox). Deriva de la clase ItemsControl, permite una gran personalización, el uso de data bindings y nos facilita un gran control sobre la interacción que el usuario realiza con él mediante el uso de eventos. Tiene dos tipos de selecciones:

  • Expandida en el mismo lugar donde se define (como lo haría un ComboBox).
  • En un popup a pantalla completa (muy útil si se va a mostrar un número elevado de elementos).

En la actual entrada vamos a realizar una introducción al uso de este control.

Para analizar las posibilidades que nos brida el control Listpicker vamos a realizar como de costumbre un ejemplo.

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo.

Tras crear el proyecto lo primero que debemos hacer es agregar la referencia a la librería del Toolkit para tener acceso al control. Para ello agregamos la referencia a la librería Microsoft.Phone.Controls.Toolkit.dll.

Nos centramos en el archivo MainPage.xaml para definir la interfaz básica de nuestro ejemplo:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
          <Button x:Name="btnBasic" Content="Uso básico"/>
          <Button x:Name="btnStyles" Content="Estilos"/>
          <Button x:Name="btnEvents" Content="Eventos"/>
     </StackPanel>
</Grid>

El resultado lo podéis ver en la captura superior. Muy simple, deseamos dividir el ejemplo en tres apartados diferenciados:

  • Uso básico. Aprenderemos que es el control utilizando sus propiedades principales.
  • Estilos. Dado la potente personalización que nos permite el control vamos a centrarnos un poco en ello.
  • Eventos. Vamos a analizar los eventos principales del control.

Por lo tanto hemos añadido tres botones. Cada uno de ellos nos llevará a una página donde trabajaremos sobre el área indicada. Añadimos los eventos de cada botón:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
          <Button x:Name="btnBasic" Content="Uso básico" Click="btnBasic_Click"/>
          <Button x:Name="btnStyles" Content="Estilos" Click="btnStyles_Click"/>
          <Button x:Name="btnEvents" Content="Eventos" Click="btnEvents_Click"/>
     </StackPanel>
</Grid>

Al pulsar sobre cada uno de los botones llevaremos al usuario a una nueva página por lo que necesitamos antes que nada añadir al proyecto las 3 páginas necesarias que utilizaremos. En el ejemplo que podéis descargar al final de la entrada se añadieron 3 páginas llamadas:

  • Basic
  • Styles
  • Events

A continuación, vamos a ver que se hace en cada uno de los botones (en la clase MainPage.xaml.cs).

private void btnBasic_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/Basic.xaml", UriKind.Relative));
}

private void btnStyles_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/Styles.xaml", UriKind.Relative));
}

private void btnEvents_Click(object sender, RoutedEventArgs e)
{
     NavigationService.Navigate(new Uri("/Events.xaml", UriKind.Relative));
}

Nada fuera de lo común. Utilizamos el servicio de navegación NavigationService para enviar al usuario a la página correspondiente. Puedes ver todo lo relacionado con el servicio de navegación NavigationService en esta entrada.

Nos centramos en la página “Basic.xaml”. Para poder utilizar el control ListPicker en nuestra interfaz lo primero que debemos hacer es añadir la referencia a la siguiente librería:

xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

Añadimos lo siguiente a la interfaz:

<StackPanel>
     <TextBlock Text="Uso Básico" FontSize="36"/>
     <toolkit:ListPicker x:Name="listPicker1"/>
</StackPanel>

Hemos añadido un control ListPicker. De momento no hemos abastecido de información al control ni tampoco hemos utilizado ninguna de sus propiedades fundamentales. Vamos a comenzar abasteciendo al control de información (utilizaremos la propiedad ItemSource para ello). Lo primero que vamos a hacer es crear una clase donde definiremos los objetos que mostrará el control:

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

     public string Nationality { get; set; }

     public string Scuderia { get; set; }
}

Hemos creado una clase Driver (Piloto) con tres propiedades:

  • Name – Nombre del Piloto.
  • Nationality – Nacionalidad del Piloto.
  • Scuderia – Escudería actual del piloto.

Vamos a crear una colección de pilotos (en nuestro ejemplo, pilotos de Formula 1) que abastecerán al ListPicker:

List<Drivers> source = new List<Drivers>();
source.Add(new Drivers() { Name = "Fernando Alonso", Nationality = "ES", Scuderia = "Ferrari" });
source.Add(new Drivers() { Name = "Lewis Hamilton", Nationality = "UK", Scuderia = "McLaren" });

listPicker1.ItemsSource = source;

Añadimos las propiedades fundamentales del control (analizamos que es cada una un poco más adelante):

<toolkit:ListPicker x:Name="listPicker1" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"
Header="Pilotos" FullModeHeader="Pilotos" CacheMode="BitmapCache" SelectionMode="Single" ExpansionMode="ExpansionAllowed"/>

Debemos definir el DataTemplate de las propiedades ItemTemplate y FullModeItemTemplate (elementos del modo a pantalla completa). Lo haremos en los propios recursos de la página:

<phone:PhoneApplicationPage.Resources>
</phone:PhoneApplicationPage.Resources>

Definimos los DataTemplate. Serán lo más sencillos posibles, un simple TextBlock que mostrará el nombre de cada piloto:

<DataTemplate x:Name="ListPickerItemTemplate">
     <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Name}" Margin="10 0 0 0"/>
     </StackPanel>
</DataTemplate>

<DataTemplate x:Name="ListPickerFullModeItemTemplate">
     <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Name}" Margin="10 0 0 0"/>
     </StackPanel>
</DataTemplate>

NOTA: En caso de no querer utilizar DataTemplates bastará con abastecer al control con una colección de cadenas (List<String> por ejemplo). Veamos un sencillo ejemplo:

<toolkit:ListPicker Header="Pilotos">
    <sys:String>Fernando Alonso</sys:String>
    <sys:String>Lewis Hamilton</sys:String>
    <sys:String>Sebastian Vettel</sys:String>
</toolkit:ListPicker>

Vamos a pararnos antes de seguir a determinar que son y para que sirven  las propiedades fundamentales del control:

  • ListPickerMode. Propiedad de dependencia de tipo ListPickerMode. Se utiliza para indicar el modo utilizado por el control. Su valor puede ser: Normal (valor por defecto, solo el elemento seleccionado es visible sin que el control esté expandido), Expanded (todos los elementos están visibles, no hace falta expandir) o Full (todos los elementos están visibles en un popup a pantalla completa).
  • Header. Propiedad de dependencia de tipo Object. Es la cabecera (normalmente un String) que aparecerá en la parte superior derecha del control.
  • FullModeHeader. Propiedad de dependencia de tipo DataTemplate. Como mencionamos al inicio del artículo, el control ListPicker tiene dos modos de expansión (selección y pantalla completa). Esta propiedad define la cabecera utilizada cuando el modo de selección es a pantalla completa.
  • ItemTemplate. Propiedad de dependencia de tipo DataTemplate.Sirve para definir la apariencia de cada elemento mostrado.
  • FullmodeItemTemplate. Propiedad de dependencia de tipo DataTemplate. Sirve para definir la apariencia de cada elemento mostrado cuando la forma de desplegar el control es a pantalla completa. Si se deja a cero, automáticamente pasamos a modo pantalla completa.
  • ExpansionMode. Propiedad de dependencia de tipo ExpansionMode. Nos sirve para obtener o indicar como se expande el ListPicker. Hay dos opciones, ExpansionAllowed o FullScreenOnly. Importante, esta propiedad solo tiene efecto cuando el modo del control (propiedad SelectionMode) es Single. Si el valor de la propiedad SelectionMode es Multiple, la propiedad SelectionMode será FullScreenOnly.
  • ItemCountThreshold. Propiedad de dependencia de tipo int. Indica el numero máximo de elementos visibles en el modo de expansión normal. Por defecto, el valor es cinco.
  • SelectionMode. Propiedad de dependencia de tipo SelectionMode. Determina el modo de selección del control. Los valores posibles son: Single, Multiple o Extended.
  • SelectedIndex. Indica o establece el índice del elemento seleccionado.
  • SelectedItem. Indica o establece el elemento seleccionado.
  • SelectionItems. Propiedad de dependencia de tipo IList. Devuelve el listado de elementos seleccionados.

A continuación, vamos a añadir un segundo ListPicker con una única diferencia, el modo de expansión será a pantalla completa (fijaos en el valor de la propiedad ExpansionMode):

<toolkit:ListPicker x:Name="listPicker2" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"
Header="Pilotos" FullModeHeader="Pilotos" CacheMode="BitmapCache" SelectionMode="Single" ExpansionMode="FullScreenOnly"/>

¿Interesante, verdad?. Continuamos, nos centramos en la página “Styles.xaml”. Añadimos los dos listpicker utilizados en los pasos básicos:

<StackPanel>
     <TextBlock Text="Estilos" FontSize="36"/>
     <toolkit:ListPicker x:Name="listPicker1" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"
     Header="Pilotos" FullModeHeader="Pilotos" CacheMode="BitmapCache" SelectionMode="Single" ExpansionMode="ExpansionAllowed"/>

     <toolkit:ListPicker x:Name="listPicker2" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"
     Header="Pilotos" FullModeHeader="Pilotos" CacheMode="BitmapCache" SelectionMode="Single" ExpansionMode="FullScreenOnly"/>
</StackPanel>

La diferencia esta vez radicará en las posibilidades de personalización de los elementos del control. Vamos a mostrar en el modo de expansión normal (Expanded) el nombre de la escudería a la que pertenece el piloto junto a su nombre. Para darle peso al nombre de la escudería, añadiremos un color de fondo (el más representativo de cada escuería):

<DataTemplate x:Name="ListPickerItemTemplate">
     <StackPanel Orientation="Horizontal">
          <Border Background="{Binding Scuderia, Converter={StaticResource scuderiaColorConverter}}" Width="60" Height="60">
               <TextBlock Text="{Binding Scuderia}" FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center"/>
          </Border>
         <TextBlock Text="{Binding Name}" Margin="10 0 0 0"/>
     </StackPanel>
</DataTemplate>

Para que el fondo del borde reciba un color dependiendo del nombre de la escudería utilizaremos un Converter:

<Converters:ScuderiaColorConverter x:Name="scuderiaColorConverter"/>

La definición del Converter:

public class ScuderiaColorConverter : System.Windows.Data.IValueConverter
{
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
          if (value is string)
          {
               switch ((string)value)
               {
                    case "Ferrari":
                         return new SolidColorBrush(Colors.Red);
                    case "McLaren":
                         return new SolidColorBrush(Colors.Gray);
                    case "RedBull":
                         return new SolidColorBrush(Colors.Blue);
               }
          }

          throw new NotSupportedException();
     }

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
     {
          throw new NotSupportedException();
     }
}

En la captura superior podéis ver el resultado conseguido. ¿Empezáis a ver las infinitas posibilidades?. Continuamos personalizando cada elemento del modo de expansión a pantalla completa (Full). En esta ocasión y gracias al mayor espacio disponible, vamos a mostrar la foto de cada piloto junto a su nombre. Para ello, antes que nada creamos una nueva carpeta (en el ejemplo llamada IMGS) donde añadiremos una foto por cada piloto. Veamos el DataTemplate correspondiente:

<DataTemplate x:Name="ListPickerFullModeItemTemplate">
     <StackPanel Orientation="Horizontal" Margin="16 21 0 20">
          <Image Source="{Binding Name, Converter={StaticResource nameImageConverter}}" Height="100" Width="100" Stretch="UniformToFill"/>
          <StackPanel>
               <TextBlock Text="{Binding Name}" FontSize="43" FontFamily="{StaticResource PhoneFontFamilyLight}"/>
               <StackPanel Orientation="Horizontal" Margin="10 0 0 0">
                    <TextBlock Text="Escudería: "/>
                    <TextBlock Text="{Binding Scuderia}" Foreground="DarkGray"/>
               </StackPanel>
          </StackPanel>
     </StackPanel>
</DataTemplate>

De nuevo hemos utilizado un Converter que recibirá el nombre del piloto y devolverá la ruta a la imágen correspondiente:

<Converters:NameImageConverter x:Name="nameImageConverter"/>

La definición del Converter:

public class NameImageConverter : System.Windows.Data.IValueConverter
{
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
          if (value is string)
               return string.Format("/IMGS/{0}.jpg", (string)value);

          throw new NotSupportedException();
     }

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
     {
          throw new NotSupportedException();
     }
}

El resultado conseguido lo puedes ver en la captura superior.

Por último, nos centramos en la página “Events.xaml”. El evento principal del control es SelectionChanged:

<StackPanel>
     <TextBlock Text="Eventos" FontSize="36"/>
     <toolkit:ListPicker x:Name="listPicker" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"
Header="Pilotos" FullModeHeader="Pilotos" CacheMode="BitmapCache" SelectionMode="Single" ExpansionMode="ExpansionAllowed" SelectionChanged="listPicker_SelectionChanged"/>
</StackPanel>

Se lanza cada vez que el elemento seleccionado cambia.

private void listPicker_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
     MessageBox.Show(((Drivers)listPicker.SelectedItem).Name);
}

Puedes ver de un vistazo todo el ejemplo realizado en video a continuación:

Tambien puedes descargar el ejemplo completo realizado:

Espero que lo visto en esta entrada os sea de utilidad. Sin duda en próximas entradas seguiremos viendo particularidades del control. Cualquier duda o sugerencia podéis plantearlas en los comentarios.

Más información

7 pensamientos en “Windows phone. Introducción al control Listpicker.

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