Traducción aproximada del artículo Getting started with Silverlight: Part 4 – Binding the data and storing some for later publicado el 6 de Octubre del 2009 en inglés por Tim Heuer.


Esta es la cuarta parte de la serie introductoria para Silverlight. Pueden ver aquí los demás artículos (y aquí los que están disponibles en español). Los archivos finales de esta parte están disponibles en C# y Visual Basic.

En la parte anterior hicimos bastante trabajo obteniendo información de un servicio público de web para luego desplegarla en un control. Sin embargo la cuadrícula (DataGrid) que usamos no es en realidad el tipo de visualización que buscamos, por lo que vamos a definir con más detalle lo que queremos. Para hacer eso vamos a usar un ItemsControl y un DataTemplate. Esta tarea nos ayudará a aprender la sintaxis para ligar o enlazar datos en XAML, y también cómo aprovechar otros mecanismos de atado de datos más poderosos.


Rediseñando la UI: eliminación del DataGrid

Bueno, después de todo ese trabajo, borremos el DataGrid, pero sólo eso. Como ya no vamos a necesitar la referencia a xmlns:data. podemos borrarla también.


Borramos el DataGrid y su espacio de nombres asociado, xmlns:data.


Como reemplazo de la cuadrícula, usaremos un ItemsControl:


<ItemsControl x:Name="Resultados"
              Margin="0,8,0,0"
              Grid.Row="1" />


Aquí es donde Blend nos va a ser útil de nuevo. El plan es usarlo para modificar el ItemTemplate. El ItemsControl sólo puede desplegar información si le especificamos cómo hacerlo. Si no hiciéramos más cambios luego de reemplazar el DataGrid veremos esto al ejecutar el programa:


ItemsControl no sabe vicualizar los datos por sí solo.


Como vemos, por sí solo el ItemsControl no tiene idea de cómo queremos visualizar la información. Es por eso que necesitamos darle instrucciones en una plantilla. Y para ello volvemos a Blend. El concepto general de lo que queremos desplegar es:


Diseño para la presentación de tweets individuales en el ItemsControl.


El cuadrado es el avatar del usuario que envió el mensaje. Usando nuestros conocimientos sobre diseño de partes anteriores podemos crear la plantilla fácilmente. En Blend, localizamos el objeto Resultados en la jerarquía y hacemos clic derecho en él para modificar el ItemTemplate, escogiendo Editar plantillas adicionales, Editar Elementos generados y , finalmente, Crear vacío…:


Para crear la plantilla en Blend, se usa el clic derecho sobre el ItemsControl.



La nueva plantilla es nombrada PlantillaDeResultados



Como producto tenemos una plantilla vacía a la que podemos agregar cosas. Yo le puse PlantillaDeResultados a la mía. Ahora estamos en el modo de edición del diseño visual y podemos usar acciones como arrastrar y mover elementos o controles. Lo que hice fue crear una distribución basada en una cuadrícula, con el siguiente resultado en XAML:


<DataTemplate x:Key="PlantillaDeResultados">
    <Grid Margin="4,0,4,8"
          d:DesignWidth="446"
          d:DesignHeight="68">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Border VerticalAlignment="Top"
                Margin="8"
                Padding="2"
                Background="White">
            <Image Height="40"
                   Width="40" />
        </Border>
        <StackPanel VerticalAlignment="Top"
                    Grid.Column="1"
                    Margin="0,4,0,0">
            <TextBlock x:Name="NombreDeAutor"
                       FontWeight="Bold" />
            <Grid Margin="0,6,0,0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="2*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <TextBlock x:Name="Mensaje"
                           TextWrapping="Wrap" />
                <TextBlock x:Name="Enviado"
                           Grid.Row="2" />
            </Grid>
        </StackPanel>
    </Grid>
</DataTemplate>


También puse el ItemTemplate en un ScrollViewer para compensar por la falta de una barra de desplazamiento en ItemsControl:


<ScrollViewer Grid.Row="2"
              HorizontalScrollBarVisibility="Disabled"
              VerticalScrollBarVisibility="Auto"
              BorderThickness="1">

    <ItemsControl x:Name="Resultados"
                  Margin="0,8,0,0"
                  Grid.Row="1"
                  ItemTemplate="{StaticResource PlantillaDeResultados}" />

</ScrollViewer>


Al final, lo que tenemos una plantilla que servirá de molde para desplegar los datos, pero todavía hay que indicarle qué hacer con esa información que recibirá.


La sintaxis de enlace de XAML

Es aquí donde viene al caso la sintaxis de enlace de datos de XAML. Como vimos hace un momento, ItemsControl está  todavía recibiendo datos. Esto es debido a que nuestro PagedCollectionView sigue asignado a Resultados.ItemsSource en el código subyacente . Para poder crear una relación entre los elementos de nuestro modelo y la plantilla de ItemTemplate necesitamos enlazarlos. Este lazo o liga entre los datos y el elemento visual que los despliega se conoce como Enlace de Datos (data binding en inglés).La sintaxis básica en XAML es:


{Binding Path=<la-ruta-hacia-los-datos>, Mode=<tipo-de-flujo-de-datos>}


La declaración tiene el potencial de ser más compleja, pero vamos a empezar con este formato básico. Por ejemplo, para enlazar el elemento Image en la plantilla al campo Avatar de nuestra clase ResultadoDeBusqueda usamos la siguiente declaración:


<Image Height="40"
       Width="40"
       Source="{Binding Path=Avatar, Mode=OneWay}" />


Y para atar el campo Autor al elemento NombreDeAutor y Tweet a Mensaje:


<TextBlock x:Name="NombreDeAutor"
           FontWeight="Bold"
           Text="{Binding Path=Autor, Mode=OneWay}" />

...

<TextBlock x:Name="Mensaje"
           TextWrapping="Wrap"
           Text="{Binding Path=Tweet, Mode=OneWay}" />


En ambos casos especificamos la modalidad unidireccional (OneWay) puesto que no vamos a modificar los datos. Con FechaPublicado vamos a elaborar un poco más para poder darle el formato apropiado. Para ello, primero necesitamos un convertidor de valores.


Implementando un convertidor de valores

Convertidores de valores son clases que implementan el contrato IValueConverter, proveyendo los métodos Convert y ConvertBack. Para FechaPublicado lo que vamos a hacer es simplemente dar un formato específico al objeto DateTime. En mi proyecto he creado una carpeta llamada Converters, y allí puse una nueva clase, ConvertidorDateTime. Éste es el código:


using System;
using System.Windows.Data;
using System.Threading;

namespace MonitorTwitter.Converters
{
    public class ConvertidorDateTime : IValueConverter
    {

        #region Miembros de IValueConverter

        public object Convert(object value, Type targetType,
                              object parameter,
                              System.Globalization.CultureInfo culture)
        {
            DateTime? fecha = value as DateTime?;

            if (culture == null)
            {
                culture = Thread.CurrentThread.CurrentUICulture;
            }

            if (fecha != null)
            {
                string formato = parameter as string;
                return fecha.Value.ToString(formato, culture);
            }

            return string.Empty;
        }

        public object ConvertBack(object value, Type targetType,
                                  object parameter,
                                  System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}




Para usarlo añadimos la siguiente declaración a la página Busqueda.xaml:


xmlns:converters="clr-namespace:MonitorTwitter.Converters"


Y luego en la sección Resources (que es donde la plantilla anterior fue definida) agregamos un recurso que apunte al convertidor:


<navigation:Page.Resources>
    <converters:ConvertidorDateTime x:Key="ConvertidorDeDateTime" />

...


Con estos cambios podemos entonces usar el convertidor en el elemento Enviado:


<TextBlock x:Name="Enviado"
           Text="{Binding Path=FechaPublicado,
                  Converter={StaticResource ConvertidorDeDateTime},
                  ConverterParameter=Envia\\do el d \\de MMMM \\de yyyy a la\\s h:mm tt}"
           Grid.Row="2" />


El XAML ahora sabe que debe usar los métodos de IValueConverter para obtener el texto a desplegar. Como resultado obtenemos la fecha en el formato deseado. Una vez hechas todas esas modificaciones, podemos ver como el enlazar los datos a los elementos de la lista nos da el diseño que habíamos planeado:


Monitor de Twitter con el nuevo diseño para desplegar resultados.


(Es cierto, usar ‘twitpic’ como término de búsqueda produce resultados… bueno, digamos que interesantes, pero la ventaja es que se puede contar con que haya nuevos tweets todo el tiempo.)

¡Excelente! No fue tan difícil ¿verdad? Conocer la sintaxis de enlace de datos es esencial para crear aplicaciones en Silverlight.


Guardando preferencias y datos de configuración

Algo que sería muy útil es poder guardar el último tweet recibido y de esa manera usarlo como punto de partida la próxima vez que se ejecute la aplicación. También sería muy conveniente guardar el historial de términos de búsqueda para poder consultarlo luego.

La manera de hacer es en Silverlight es mediante el almacenaje aislado (Isolated Storage). Este mecanismo permite que una aplicación con pocos privilegios pueda guardar datos simples. Para más información sobre el almacenaje aislado consulten:



Voy a agregar una clase auxiliar a la carpeta de Model para que nos asista en guardar y en leer tales datos. El proceso básico para ese propósito es mediante crear un  archivo en el almacenaje aislado. Vamos a utilizar IsolatedStorageSettings para guardar pares de etiqueta y valor (en nuestro caso, término de búsqueda y último ID). Es código resultante es:


using System.IO.IsolatedStorage;

namespace MonitorTwitter.Model
{
  public class Almacén
  {
     internal static string ObtenerÚltimoTweetId(string términoDeBúsqueda)
     {
        if (IsolatedStorageSettings
            .ApplicationSettings.Contains(términoDeBúsqueda))
        {
           return IsolatedStorageSettings
               .ApplicationSettings[términoDeBúsqueda].ToString();
        }
        else
        {
           return "0";
        }
     }

     internal static void GuardarÚltimoTweetId(string términoDeBúsqueda,
                                               string útimoId)
     {
        IsolatedStorageSettings
            .ApplicationSettings[términoDeBúsqueda] = útimoId;
     }
  }
}


Y en código subyacente Busqueda.xaml.cs añadimos lo siguiente justo después de manipular el indicador de actividad en BuscarTweets:


_últimoId = Almacén.ObtenerÚltimoTweetId(Termino.Text);


Y finalmente en OnReadCompleted luego de cerrar el XMLReader insertamos esto:


Almacén.GuardarÚltimoTweetId(Termino.Text, _últimoId);


Guardando así los términos de búsqueda y el último ID en caso de haber hallado resultados.


Resumen

En esta parte diseñamos una plantilla para un control, creamos enlaces a datos usando la sintaxis básica de XAML para ese propósito, añadimos un convertidor de valores para dar un formato diferente a la información, y guardamos datos del programa en el almacenaje aislado para uso posterior.

Ya tenemos la aplicación prácticamente lista en términos de funcionalidad. Así que dediquemos un poco de esfuerzo en pulir la interfase al usuario.

En la siguiente parte vamos a añadir nuevos controles para proveer al usuario una mejor experiencia de uso gracias a la información que hemos guardado.

Etiquetas asignadas:
 

2 Respuestas a “Introducción a Silverlight – Parte 4: Atando los datos y guardando algunos para uso posterior”

  1. [...] Introducción a Silverlight – Parte 4: Atando los datos y guardando algunos para uso posterior [...]

  2. Jhon dice:

    Te felicito por tan excelente aporte

Responder



Licencia de uso

El contenido de las traducciones está sujeto a los términos de protección de derechos de uso de los autores originales quienes han autorizado su publicación en este blog. Asegúrese de entender los terminos de la licencia de cada autor antes de usar tal contenido.

Mis propios artículos son publicados bajo los términos de la Licencia Reconocimiento-Compartir bajo la misma licencia 3.0 Estados Unidos de Creative Commons:

Creative Commons License
Blog de Maromas Digitales by Maromas Digitales, LLC is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 3.0 Estados Unidos License.

License

The contents of all translated articles is subject to the copyright and licensing terms of the original authors and has been published here with their express permission. Verify the original author's licensing terms before using the contents of these articles.

My own articles are licensed under the Creative Commons Attribution-Share Alike 3.0 United States License:

Creative Commons License
Blog de Maromas Digitales by Maromas Digitales, LLC is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.