Enlazando datos a controles

Este artículo es una traducción del artículo original encontrado en: http://create.msdn.com/en-US/education/quickstarts/Data_Binding_to_Controls.

Muchas aplicaciones de Windows Phone muestran datos en controles.  En muchos casos, los datos son un objeto de negocio o una colección de objetos de negocio tales como cotizaciones de bolsa, noticias, o imágenes. Además, a menudo, se desea que el usuario pueda seleccionar un elemento de una lista y luego mostrar los detalles acerca de ese elemento en otro control, como un cuadro de texto.

Este artículo te muestra, cómo enlazar un control a un solo elemento y enlazar un control de lista a una colección de elementos.  Adicionalmente se explica cómo personalizar la presentación de los elementos en un control, implementar una vista de detalles basados en una selección, y convertir los datos para su visualización.

Este tutorial contiene las siguientes secciones:

  • Enlazando un control a un único elemento
  • Enlazando un control a una colección de objetos
  • Visualizando elementos en un control utilizando una Plantilla de Datos
  • Agregando una vista de detalles
  • Convirtiendo datos para visualizarse en controles

Enlazando un control a un único elemento

Un enlace de datos se compone de un objetivo y una fuente.  El objetivo de un enlace normalmente es una propiedad de un control.  El objetivo debe ser un DependencyProperty.

A continuación se muestra un ejemplo de enlace de un control a un solo elemento.  El objetivo es la propiedad Text de un control de cuadro de texto.  La fuente es una clase simple llamada Recording.

 

XAML

 

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<TextBox VerticalAlignment="Top" IsReadOnly="True" Margin="5"

TextWrapping="Wrap" Height="120" Width="400"

Text="{Binding}" x:Name="textBox1" />

</Grid>

C#

// Constructor

public MainPage()

{

InitializeComponent();

// Establecer el contexto de datos a una nueva grabación.

textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live",

new DateTime(2008, 2, 5));

}

//Un objeto de negocio simple.

public class Recording

{

public Recording() { }

public Recording(string artistName, string cdName, DateTime release)

{

Artist = artistName;

Name = cdName;

ReleaseDate = release;

}

public string Artist { get; set; }

public string Name { get; set; }

public DateTime ReleaseDate { get; set; }

// Reemplazar el método ToString.

public override string ToString()

{

return Name + " by " + Artist + ", Released: " + ReleaseDate.ToShortDateString();

}

}

 

Visual Basic

 

‘Constructor

Public Sub New()

InitializeComponent()

Establecer los datos de contexto para una nueva grabación.

textBox1.DataContext = New Recording("Chris Sells", "Chris Sells Live", _

New DateTime(2008, 2, 5))

End Sub

Public Class Recording

Public Sub New()

End Sub

Public Sub New(ByVal artistName As String, ByVal cdName As String, _

ByVal release As DateTime)

Artist = artistName

Name = cdName

ReleaseDate = release

End Sub

Public Property Artist As String

Public Property Name As String

Public Property ReleaseDate As DateTime

Reemplazar el ToString.

Public Overloads Overrides Function ToString() As String

Return Name + " by " + Artist + ", Released: " + releaseDate.ToShortDateString()

End Function

End Class

Cuando ejecutas la aplicación, se verá algo como esto:

clip_image002

Para mostrar una grabación de música en un cuadro de texto, la propiedad Text del control se establece a un Binding utilizando una extensión de marcado.  En este ejemplo, el modo de enlace por defecto es BindingMode.OneWay, lo que significa que los datos se recuperan de la fuente, pero los cambios no se propagan de nuevo a ella.  Para obtener más información sobre las extensiones de marcado y la sintaxis, consulta Binding Markup Extension en la documentación de Silverlight en MSDN.

La clase Recording tiene tres propiedades públicas y reemplaza el método ToString.  Las propiedades son Artist, Name y ReleaseDate.  El método ToString es importante porque si no se especifica el formato, el método ToString es llamado en el objeto enlazado para propósitos de visualización.  La propiedad Binding.Source no se establece directamente, sino que la propiedad FrameworkElement.DataContext para el control TextBox se establece en un nuevo objeto Recording.

Enlazando un control a una colección de objetos 

 

El ejemplo anterior muestra la sintaxis que se utiliza para enlazar datos a controles, pero en realidad, este caso no es muy realista.  Un escenario más común, es enlazar a una colección de objetos de negocio.  La clase genérica ObservableCollection es una buena opción para colecciones enlazables a datos, ya que implementa las interfaces INotifyPropertyChanged y INotifyCollectionChanged.  Estas interfaces proporcionan notificación de cambios a los controles enlazados cuando un elemento en la lista cambia o una propiedad en la lista per se cambia.  Si quieres que tus controles enlazados se actualicen con los cambios a las propiedades de los objetos en la colección, el objeto de negocio también debe implementar INotifyPropertyChanged.

En el siguiente ejemplo se enlaza un conjunto de objetos de tipo Recording a un ComboBox. Para probar este ejemplo, haz clic en la flecha hacia abajo en la lista desplegable para ver la lista de registros enlazados.

Get Microsoft Silverlight

XAML

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"

Foreground="Black" FontSize="18" Height="50" Width="400"/>

</Grid>

 

C#

 

public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();

public Page()

{

InitializeComponent();

// Añadir elementos a la colección.

MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",

new DateTime(2008, 2, 5)));

MyMusic.Add(new Recording("Luka Abrus",

"The Road to Redmond", new DateTime(2007, 4, 3)));

MyMusic.Add(new Recording("Jim Hance",

"The Best of Jim Hance", new DateTime(2007, 2, 6)));

// Establecer el contexto de datos para el combo Box

ComboBox1.DataContext = MyMusic;

}

 

 

 

 

 

Visual Basic

 

Public MyMusic As New ObservableCollection(Of Recording)()

Public Sub New()

InitializeComponent()

Añadir elementos a la colección.

MyMusic.Add(New Recording("Chris Sells", "Chris Sells Live", _

New DateTime(2008, 2, 5)))

MyMusic.Add(New Recording("Luka Abrus", "The Road to Redmond", _

New DateTime(2007, 4, 3)))

MyMusic.Add(New Recording("Jim Hance", "The Best of Jim Hance", _

New DateTime(2007, 2, 6)))

Establecer el contexto de datos para el combo box.

ComboBox1.DataContext = MyMusic

End Sub

 

Para visualizar las grabaciones de música en el ComboBox, la propiedad ItemsControl.ItemsSource del control establece un Binding, y la propiedad  FrameworkElement.DataContext para el control ComboBox se establece en la colección de objetos de tipo Recording, la cual proporciona la fuente de enlace.  Se crea un ComboBoxItem para cada elemento de la colección. ToString se llama automáticamente en cada objeto Recording para mostrarlo en el elemento del combo box. 

Visualizando elementos en un control utilizando una Plantilla de Datos

Puedes mostrar elementos en una lista utilizando el método ToString.  Sin embargo, un escenario más común es proporcionar una visualización personalizada de elementos de datos enlazados mediante un DataTemplate.  Un DataTemplate te permite personalizar la forma en la que se visualizan los elementos de una lista en un control.  Normalmente, estableces la Plantilla de Datos usando la propiedad ContentControl.ContentTemplate en un control de contenido o la propiedad ItemsControl.ItemTemplate en un control de elementos.

El siguiente ejemplo muestra la misma lista de grabaciones enlazada a un Combo Box utilizando una Plantilla de Datos.  Un Combo Box es un ItemsControl, lo que significa puedes establecer una Plantilla de Datos para cada uno de los elementos, al establecer su propiedad ItemTemplate a una Plantilla de Datos.  Para probar este ejemplo, haz clic en la flecha hacia abajo para ver la lista de grabaciones.  Observa cómo las grabaciones tienen un aspecto diferente que el ejemplo anterior.  El artista y el nombre del CD se muestran en un formato personalizado.

Get Microsoft Silverlight

XAML

 

<ComboBox x:Name="ComboWithTemplate" Margin="5"

Width="450" Height="50" HorizontalAlignment="Left"

ItemsSource="{Binding}" Foreground="Black" FontSize="18" >

<ComboBox.ItemTemplate>

<DataTemplate>

<StackPanel Orientation="Horizontal" Margin="2">

<TextBlock Text="Artist:" Margin="2" />

<TextBlock Text="{Binding Artist}" Margin="2" />

<TextBlock Text="CD:" Margin="10,2,0,2" />

<TextBlock Text="{Binding Name}" Margin="2" />

</StackPanel>

</DataTemplate>

</ComboBox.ItemTemplate>

</ComboBox>

 

En el XAML, puedes ver la definición de la Plantilla de Datos.  La Plantilla de Datos contiene un StackPanel con cuatro controles TextBlock.  El StackPanel tiene una orientación horizontal, de modo que los cuatro controles de bloque de texto aparecerán uno al lado del otro.  Dos de los controles TextBlock están enlazados a las propiedades Artist y Name de un objeto Recording. Los otros dos controles TextBlock muestran su texto estático. Para cada elemento enlazado, el enlace proporciona la ruta hacia la propiedad en el objeto Recording.  Como en el ejemplo anterior, este enlace se basa en el contexto de datos que se establece en la lista de grabaciones.  

Este XAML utiliza la sintaxis de elementos de propiedad.  Para obtener más información acerca de la sintaxis de XAML, consulta XAML [Xaml.docx].  Para obtener más información sobre la distribución de controles, consulta Distribución en la Pantalla [Distribución en la pantalla.docx].

 

Agregando una vista de detalles

Para mostrar los detalles de un elemento cuando es seleccionado en una colección, tienes que crear la interfaz de usuario adecuada y enlazarla a los datos que quieres visualizar.  Adicionalmente, debes utilizar un CollectionViewSource  como contexto de datos, para permitir que la vista de detalles se enlace al elemento actual.

El siguiente ejemplo muestra la misma lista de grabaciones, pero esta vez la lista es el origen de datos de una instancia de CollectionViewSource.  El contexto de datos de la raíz se establece al CollectionViewSource, y el Combo Box y la vista de detalles heredan el contexto de datos de la raíz.  Esto permite que el Combo Box muestre la misma lista de elementos, mientras que la vista de detalles muestra información acerca del elemento actual.

Para probar este ejemplo, haz clic en la flecha hacia abajo y selecciona diferentes grabaciones. Nota que el artista, nombre del CD, y fecha de lanzamiento aparecen en una vista de detalles debajo del Combo Box.

Get Microsoft Silverlight

XAML

<!– Interfaz de usuario para visualizar los detalles –>

<StackPanel x:Name="RecordingDetails">

<TextBlock FontWeight="Bold" Text="{Binding Artist}" Margin="5,0,0,0"/>

<TextBlock FontStyle="Italic" Text="{Binding Name}" Margin="5,0,0,0"/>

<TextBlock Text="{Binding ReleaseDate}" Margin="5,0,0,0" />

</StackPanel>

 

C#

 

/ / ComboWithTemplate.DataContext = MyMusic;

LayoutRoot.DataContext = new CollectionViewSource { Source = MyMusic };

 

 

Visual Basic

 

‘ComboWithTemplate.DataContext = MyMusic

LayoutRoot.DataContext = New CollectionViewSource With {.Source = MyMusic}

 

En este ejemplo, se agrega un StackPanel al control de usuario que contiene el Combo Box existente.  Un rectángulo sirve de línea divisoria debajo del Combo Box.  Posteriormente hay un StackPanel que contiene cuatro bloques de texto para mostrar los detalles de la grabación. La propiedad TextBlock.Text de cada bloque de texto, está enlazada a una propiedad en el objeto Recording.

Convirtiendo datos para visualizarse en controles

Si deseas dar formato y mostrar un tipo que no sea una cadena en un control, como un TextBox, puedes utilizar un convertidor.  Por ejemplo, puedes mostrar una etiqueta y una fecha con formato, en lugar de mostrar sólo la fecha. (Toma en cuenta que puedes utilizar la propiedad BindingBase.StringFormat si solo quieres dar formato a la fecha)

El siguiente ejemplo muestra la implementación de un convertidor para la fecha de lanzamiento en la lista de grabaciones.  Para probar este ejemplo, haz clic en la flecha hacia abajo y selecciona diferentes grabaciones.  Nota que la fecha de lanzamiento en la lista desplegable y en la vista de detalles se muestra en un formato personalizado.

Get Microsoft Silverlight

XAML

 

<phone:PhoneApplicationPage

x:Class="MyExample.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:MyExample"

> 

<phone:PhoneApplicationPage.Resources>

<local:StringFormatter x:Key="StringConverter"/>

</phone:PhoneApplicationPage.Resources>

<!– ContentPanel – el contenido de lugar aquí –>

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<ComboBox x:Name="ComboWithTemplate" Margin="5"

Width="450" Height="50" HorizontalAlignment="Left"

ItemsSource="{Binding}" Foreground="Black" FontSize="18" >

<ComboBox.ItemTemplate>

<DataTemplate>

<StackPanel Orientation="Horizontal" Margin="2">

<TextBlock Text="Artist:" Margin="2" />

<TextBlock Text="{Binding Artist}" Margin="2" />

<TextBlock Text="CD:" Margin="10,2,0,2" />

<TextBlock Text="{Binding Name}" Margin="2" />

</StackPanel>

</DataTemplate>

</ComboBox.ItemTemplate>

</ComboBox>

<!– La interfaz de usuario para ver los detalles –>

<StackPanel x:Name="RecordingDetails">

<TextBlock Text="{Binding Artist}" />

<TextBlock Text="{Binding Name}" />

<TextBlock Text="{Binding ReleaseDate,

Converter={StaticResource StringConverter},

ConverterParameter=Released: \{0:d\}}" />

</StackPanel>

</StackPanel>

</phone:PhoneApplicationPage>

C#

public class StringFormatter : IValueConverter

{

/ / Esto convierte el objeto de valor a la cadena para mostrar.

/ / Esto funciona con tipos más simples

 public object Convert(object value, Type targetType,

object parameter, System.Globalization.CultureInfo culture)

{

// Recuperar la cadena de formato y lo utilizan para dar formato al valor.

string formatString = parameter as string;

if (!string.IsNullOrEmpty(formatString))

{

return string.Format(culture, formatString, value);

}

/ / Si la cadena de formato es nulo o vacío, simplemente

/ / Es llamado el valor ToString ()

 return value.ToString();

}

/ / No hay necesidad de aplicar la conversión de nuevo en un solo sentido vinculante

public object ConvertBack(object value, Type targetType,

object parameter, System.Globalization.CultureInfo culture)

{

throw new NotImplementedException();

}

}

Visual Basic

Public Class StringFormatter

Implements IValueConverter

Esto convierte el objeto DateTime a la cadena para mostrar.

Public Function Convert(ByVal value As Object, ByVal targetType As Type, _

ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _

As Object Implements IValueConverter.Convert

Recupera la cadena y lo utiliza para dar formato al valor.

Dim formatString As String = TryCast(parameter, String)

If Not String.IsNullOrEmpty(formatString) Then

Return String.Format(culture, formatString, value)

End If

Si la cadena de formato es nulo o vacío, simplemente llama a ToString ()

Sobre el valor.

 Return value.ToString()

End Function

No hay necesidad de aplicar la conversión de nuevo en un solo sentido vinculante

Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, _

ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _

As Object Implements IValueConverter.ConvertBack

Throw New NotImplementedException()

End Function

End Class

Un convertidor es una clase que implementa la interfaz IValueConverter.  IValueConverter tiene dos métodos, Convert y ConvertBack.  Para un enlace unidireccional de la fuente de datos hacia el destino del enlace, solo tienes que implementar el método Convert.  El convertidor en este ejemplo es bastante genérico.  Puedes pasar el formato de cadena como un parámetro, y utilizar en el convertidor el método Format para realizar la conversión.  Si no se pasa cadena para el formato, el convertidor regresa el resultado de llamar ToString en el objeto.

Una vez que implementes el convertidor, creas una instancia de la clase del convertidor e indicas a los enlaces que utilice dicha instancia.  En este ejemplo, esto se realiza en XAML.  La instancia del convertidor se crea como un recurso estático y se le asigna una clave.  La clave es usada cuando propiedad del convertidor se establece en el enlace. 

Para obtener más información acerca de cómo convertir datos para la visualización en los controles, consulta IValueConverter en la documentación de Silverlight en MSDN.