Creación de una plantilla de datos de Xamarin.Forms
Las plantillas de datos se pueden crear insertadas, en un objeto ResourceDictionary, o bien a partir de un tipo personalizado o un tipo de celda de Xamarin.Forms adecuado. En este artículo se explora cada una de las técnicas.
Un escenario de uso común para un elemento DataTemplate
es mostrar datos de una colección de objetos en un control ListView
. La apariencia de los datos de cada celda del control ListView
se puede administrar mediante el establecimiento de la propiedad ListView.ItemTemplate
en un elemento DataTemplate
. Se pueden usar varias técnicas para realizar esta acción:
- Creación de una plantilla de datos insertada.
- Creación de una plantilla de datos con un tipo.
- Creación de una plantilla de datos como un recurso.
Independientemente de la técnica que se use, el resultado es que la apariencia de cada celda del control ListView
se define mediante un elemento DataTemplate
, como se muestra en las capturas de pantalla siguientes:
Creación de una plantilla de datos insertada
La propiedad ListView.ItemTemplate
se puede establecer en un elemento DataTemplate
insertado. Una plantilla insertada, que es la que se coloca como elemento secundario directo de una propiedad de control adecuada, se debe usar si no hay ninguna necesidad de reutilizar la plantilla de datos en otros puntos. Los elementos especificados en el elemento DataTemplate
definen la apariencia de cada celda, como se muestra en el ejemplo de código XAML siguiente:
<ListView Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
<local:Person Name="John" Age="37" Location="USA" />
<local:Person Name="Tom" Age="42" Location="UK" />
<local:Person Name="Lucas" Age="29" Location="Germany" />
<local:Person Name="Tariq" Age="39" Location="UK" />
<local:Person Name="Jane" Age="30" Location="USA" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
...
<Label Text="{Binding Name}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Age}" />
<Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
El elemento secundario de un elemento DataTemplate
insertado debe ser de tipo Cell
, o bien derivarse de él. En este ejemplo se usa un ViewCell
, que procede de Cell
. Aquí, el diseño dentro de ViewCell
se administra mediante un control Grid
. Grid
contiene tres instancias de Label
que enlazan sus propiedades Text
a las propiedades adecuadas de cada objeto Person
de la colección.
El código de C# equivalente se muestra en el ejemplo de código siguiente:
public class WithDataTemplatePageCS : ContentPage
{
public WithDataTemplatePageCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
var personDataTemplate = new DataTemplate(() =>
{
var grid = new Grid();
...
var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
var ageLabel = new Label();
var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
return new ViewCell { View = grid };
});
Content = new StackLayout
{
Margin = new Thickness(20),
Children = {
...
new ListView { ItemsSource = people, ItemTemplate = personDataTemplate, Margin = new Thickness(0, 20, 0, 0) }
}
};
}
}
En C#, el elemento DataTemplate
insertado se crea mediante una sobrecarga del constructor que especifica un argumento Func
.
Creación de una plantilla de datos con un tipo
La propiedad ListView.ItemTemplate
también se puede establecer en un elemento DataTemplate
creado a partir de un tipo de celda. La ventaja de este enfoque es que la apariencia definida por el tipo de celda se puede reutilizar en varias plantillas de datos en toda la aplicación. En el código XAML siguiente se muestra un ejemplo de este enfoque:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataTemplates"
...>
<StackLayout Margin="20">
...
<ListView Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
...
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<local:PersonCell />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
En este caso, la propiedad ListView.ItemTemplate
se establece en un elemento DataTemplate
creado a partir de un tipo personalizado que define el aspecto de la celda. El tipo personalizado se debe derivar del tipo ViewCell
, como se muestra en el ejemplo de código siguiente:
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataTemplates.PersonCell">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Age}" />
<Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
Dentro de ViewCell
, el diseño se administra mediante un control Grid
. Grid
contiene tres instancias de Label
que enlazan sus propiedades Text
a las propiedades adecuadas de cada objeto Person
de la colección.
El código de C# equivalente se muestra en el ejemplo siguiente:
public class WithDataTemplatePageFromTypeCS : ContentPage
{
public WithDataTemplatePageFromTypeCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
Content = new StackLayout
{
Margin = new Thickness(20),
Children = {
...
new ListView { ItemTemplate = new DataTemplate(typeof(PersonCellCS)), ItemsSource = people, Margin = new Thickness(0, 20, 0, 0) }
}
};
}
}
En C#, DataTemplate
se crea mediante una sobrecarga del constructor que especifica el tipo de celda como argumento. El tipo de celda se debe derivar del tipo ViewCell
, como se muestra en el ejemplo de código siguiente:
public class PersonCellCS : ViewCell
{
public PersonCellCS()
{
var grid = new Grid();
...
var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
var ageLabel = new Label();
var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
View = grid;
}
}
Nota:
Tenga en cuenta que Xamarin.Forms también incluye tipos de celda que se pueden usar para mostrar datos simples en celdas ListView
. Para obtener más información, vea Apariencia de una celda.
Creación de una plantilla de datos con un recurso
Las plantillas de datos también se pueden crear como objetos reutilizables en un objeto ResourceDictionary
. Esto se consigue mediante la asignación de un atributo x:Key
único a cada declaración, para proporcionarle una clave descriptiva en el objeto ResourceDictionary
, como se muestra en el ejemplo de código XAML siguiente:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="personTemplate">
<ViewCell>
<Grid>
...
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="20">
...
<ListView ItemTemplate="{StaticResource personTemplate}" Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
...
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</ContentPage>
El elemento DataTemplate
se asigna a la propiedad ListView.ItemTemplate
mediante la extensión de marcado StaticResource
. Tenga en cuenta que aunque el elemento DataTemplate
se defina en el objeto ResourceDictionary
de la página, también se puede definir en el nivel de control o aplicación.
En el ejemplo de código siguiente se muestra la página equivalente en C#:
public class WithDataTemplatePageCS : ContentPage
{
public WithDataTemplatePageCS ()
{
...
var personDataTemplate = new DataTemplate (() => {
var grid = new Grid ();
...
return new ViewCell { View = grid };
});
Resources = new ResourceDictionary ();
Resources.Add ("personTemplate", personDataTemplate);
Content = new StackLayout {
Margin = new Thickness(20),
Children = {
...
new ListView { ItemTemplate = (DataTemplate)Resources ["personTemplate"], ItemsSource = people };
}
};
}
}
El elemento DataTemplate
se agrega a ResourceDictionary
con el método Add
, que especifica una cadena Key
que se usa para hacer referencia al elemento DataTemplate
al recuperarlo.
Resumen
En este artículo se ha explicado cómo crear plantillas de datos, insertadas, a partir de un tipo personalizado, o bien en un objeto ResourceDictionary
. Una plantilla insertada se debe usar si no es necesario volver a utilizarla en otro lugar. Como alternativa, se puede reutilizar una plantilla de datos si se define como un tipo personalizado, o como un recurso de nivel de página o el nivel de aplicación de nivel de control.