Uso de varios diseños de celda en un elemento ListView
La capacidad para definir un diseño de celda personalizado proporciona mucho poder para controlar la experiencia del usuario. Pero si las diferentes filas representan diferentes tipos de elementos, nos conviene tener plantillas de celda distintas para cada uno de esos tipos.
Considere la posibilidad de tener nuestra aplicación doméstica inteligente con un elemento ListView
de dispositivos inteligentes. Si pensamos en el diseño ideal para una fila de videoportero y para una fila de termostato, es muy probable que sean diferentes.
En esta unidad, vamos a usar DataTemplateSelector
para mostrar plantillas de celda diferentes en nuestro elemento ListView
.
¿Qué es un DataTemplateSelector?
Podemos usar DataTemplateSelector
con el fin de elegir un valor DataTemplate
para cada elemento de la colección de origen. Dado que DataTemplate
define el tipo de celda que se usará, con el uso de plantillas diferentes la celda se cambia.
Recuerde que, en caso de que todas las filas son iguales, si usamos un elemento ViewCell
o algo más sencillo, como un elemento TextCell
, necesitamos seguir los pasos siguientes:
- Crear un control
DataTemplate
. - Indicar el valor
DataTemplate
que va a usar el tipo de celda. - Asignar el valor
DataTemplate
a la propiedadListView.ItemTemplate
.
Al hacer esto en XAML queda limpio e incluso puede que no parezcan tres pasos independientes:
...
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
...
Pero si queremos que nuestras filas sean capaces de usar diferentes diseños, nuestra propiedad ListView.ItemTemplate
se establecerá en un valor DataTemplateSelector
personalizado ListView.ItemTemplate
DataTemplate
. Después, el elemento ListView
le preguntará al selector qué DataTemplate
se usará para cada fila.
Creación de un DataTemplateSelector
Para crear el selector, tenemos que agregar una clase que se derive de DataTemplateSelector
e invalide el método OnSelectTemplate
:
class SmartDeviceSelector : Xamarin.Forms.DataTemplateSelector
{
protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
{
...
}
}
El elemento de colección enlazado a datos (por ejemplo, el videoportero o el termostato), se pasa a OnSelectTemplate
como el parámetro item
. A menudo, se va a usar la lógica de bifurcación sencilla para devolver el valor DataTemplate
correcto:
...
protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
{
if (item is doorbell)
return DoorbellTemplate;
else
return GenericTemplate;
}
...
En el código anterior, no se crean instancias de o GenericTemplate
. Por motivos de rendimiento, se volverán a usar las mismas instancias de plantilla. Por lo general, las instancias de plantilla se pueden crear como parte del constructor del selector. Se necesita una instancia de plantilla por cada tipo de celda.
Por motivos de rendimiento parecidos, siempre se podrá volver a usar la propia instancia de selector. Cuando se usa XAML, esto se puede hacer más fácilmente si se crea en ResourceDictionary
y se hace referencia como un elemento StaticResource
:
<ContentPage.Resources>
<ResourceDictionary>
<local:CharacterSelector x:Key="SmartDeviceSelector"/>
</ResourceDictionary>
</ContentPage.Resources>
<ListView x:Name="listMessages"
ItemTemplate="{StaticResource SmartDeviceSelector}"
ItemsSource="{Binding ChatHistory}"
HasUnevenRows="True"
... />