Creación de un elemento DataTemplateSelector de Xamarin.FormsCreating a Xamarin.Forms DataTemplateSelector

Descargar ejemplo Descargar el ejemploDownload Sample Download the sample

Un elemento DataTemplateSelector se puede usar para elegir una plantilla de datos en tiempo de ejecución según el valor de una propiedad enlazada a datos. Esto permite aplicar varias instancias de DataTemplate al mismo tipo de objeto, para personalizar la apariencia de objetos concretos. En este artículo se explica cómo crear y consumir una instancia de DataTemplateSelector.A DataTemplateSelector can be used to choose a DataTemplate at runtime based on the value of a data-bound property. This enables multiple DataTemplates to be applied to the same type of object, to customize the appearance of particular objects. This article demonstrates how to create and consume a DataTemplateSelector.

Un selector de plantillas de datos habilita escenarios como el enlace de ListView a una colección de objetos, donde la apariencia de cada objeto de ListView se puede elegir en tiempo de ejecución mediante el selector de plantillas de datos devolviendo un elemento DataTemplate determinado.A data template selector enables scenarios such as a ListView binding to a collection of objects, where the appearance of each object in the ListView can be chosen at runtime by the data template selector returning a particular DataTemplate.

Creación de DataTemplateSelectorCreating a DataTemplateSelector

Un selector de plantillas de datos se implementa mediante la creación de una clase que hereda de DataTemplateSelector.A data template selector is implemented by creating a class that inherits from DataTemplateSelector. Después, se reemplaza el método OnSelectTemplate para devolver un elemento DataTemplate, como se muestra en el ejemplo de código siguiente:The OnSelectTemplate method is then overridden to return a particular DataTemplate, as shown in the following code example:

public class PersonDataTemplateSelector : DataTemplateSelector
{
  public DataTemplate ValidTemplate { get; set; }
  public DataTemplate InvalidTemplate { get; set; }

  protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
  {
    return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
  }
}

El método OnSelectTemplate devuelve la plantilla adecuada en función del valor de la propiedad DateOfBirth.The OnSelectTemplate method returns the appropriate template based on the value of the DateOfBirth property. La plantilla que se devuelve es el valor de las propiedades ValidTemplate o InvalidTemplate, que se establecen cuando se consume PersonDataTemplateSelector.The template to return is the value of the ValidTemplate property or the InvalidTemplate property, which are set when consuming the PersonDataTemplateSelector.

Después, se puede asignar una instancia de la clase de selector de plantilla de datos a propiedades de control de Xamarin.Forms como ListView.ItemTemplate.An instance of the data template selector class can then be assigned to Xamarin.Forms control properties such as ListView.ItemTemplate. Para obtener una lista de las propiedades válidas, vea Creación de una plantilla de datos.For a list of valid properties, see Creating a DataTemplate.

LimitacionesLimitations

Las instancias de DataTemplateSelector tienen las limitaciones siguientes:DataTemplateSelector instances have the following limitations:

  • La subclase DataTemplateSelector siempre debe devolver la misma plantilla para los mismos datos si se consultan varias veces.The DataTemplateSelector subclass must always return the same template for the same data if queried multiple times.
  • La subclase DataTemplateSelector no debe devolver otra subclase DataTemplateSelector.The DataTemplateSelector subclass must not return another DataTemplateSelector subclass.
  • La subclase DataTemplateSelector no debe devolver nuevas instancias de DataTemplate en cada llamada.The DataTemplateSelector subclass must not return new instances of a DataTemplate on each call. En su lugar, se debe devolver la misma instancia.Instead, the same instance must be returned. De lo contrario, se creará una fuga de memoria y se deshabilitará la virtualización.Failure to do so will create a memory leak and will disable virtualization.
  • En Android, no puede haber más de 20 plantillas de datos diferentes por ListView.On Android, there can be no more than 20 different data templates per ListView.

Consumo de una instancia de DataTemplateSelector en XAMLConsuming a DataTemplateSelector in XAML

En XAML, se pueden crear instancias de PersonDataTemplateSelector si se declara como un recurso, como se muestra en el ejemplo de código siguiente:In XAML, the PersonDataTemplateSelector can be instantiated by declaring it as a resource, as shown in the following code example:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Selector;assembly=Selector" x:Class="Selector.HomePage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="validPersonTemplate">
                <ViewCell>
                   ...
                </ViewCell>
            </DataTemplate>
            <DataTemplate x:Key="invalidPersonTemplate">
                <ViewCell>
                   ...
                </ViewCell>
            </DataTemplate>
            <local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
                ValidTemplate="{StaticResource validPersonTemplate}"
                InvalidTemplate="{StaticResource invalidPersonTemplate}" />
        </ResourceDictionary>
    </ContentPage.Resources>
  ...
</ContentPage>

Este objeto ResourceDictionary de nivel de página define dos instancias de DataTemplate y una instancia de PersonDataTemplateSelector.This page level ResourceDictionary defines two DataTemplate instances and a PersonDataTemplateSelector instance. La instancia de PersonDataTemplateSelector establece sus propiedades ValidTemplate y InvalidTemplate en las instancias de DataTemplate correspondientes mediante la extensión de marcado StaticResource.The PersonDataTemplateSelector instance sets its ValidTemplate and InvalidTemplate properties to the appropriate DataTemplate instances by using the StaticResource markup extension. Tenga en cuenta que aunque los recursos se definen en el objeto ResourceDictionary de la página, también se pueden definir en el nivel de control o aplicación.Note that while the resources are defined in the page's ResourceDictionary, they could also be defined at the control level or application level.

La instancia de PersonDataTemplateSelector se consume asignándola a la propiedad ListView.ItemTemplate, como se muestra en el ejemplo de código siguiente:The PersonDataTemplateSelector instance is consumed by assigning it to the ListView.ItemTemplate property, as shown in the following code example:

<ListView x:Name="listView" ItemTemplate="{StaticResource personDataTemplateSelector}" />

En tiempo de ejecución, ListView llama al método PersonDataTemplateSelector.OnSelectTemplate para cada uno de los elementos de la colección subyacente, y la llamada pasa el objeto de datos como el parámetro item.At runtime, the ListView calls the PersonDataTemplateSelector.OnSelectTemplate method for each of the items in the underlying collection, with the call passing the data object as the item parameter. Después, el elemento DataTemplate devuelto por el método se aplica a ese objeto.The DataTemplate that is returned by the method is then applied to that object.

En las capturas de pantalla siguientes se muestra el resultado de la aplicación de PersonDataTemplateSelector por parte de ListView a cada objeto de la colección subyacente:The following screenshots show the result of the ListView applying the PersonDataTemplateSelector to each object in the underlying collection:

Cualquier objeto Person que tenga un valor de propiedad DateOfBirth mayor o igual a 1980 se muestra en color verde, y los demás objetos se muestran en color rojo.Any Person object that has a DateOfBirth property value greater than or equal to 1980 is displayed in green, with the remaining objects being displayed in red.

Consumo de una instancia de DataTemplateSelector en C#Consuming a DataTemplateSelector in C#

En C#, se pueden crear instancias de PersonDataTemplateSelector y asignarlas a la propiedad ListView.ItemTemplate, como se muestra en el ejemplo de código siguiente:In C#, the PersonDataTemplateSelector can be instantiated and assigned to the ListView.ItemTemplate property, as shown in the following code example:

public class HomePageCS : ContentPage
{
  DataTemplate validTemplate;
  DataTemplate invalidTemplate;

  public HomePageCS ()
  {
    ...
    SetupDataTemplates ();
    var listView = new ListView {
      ItemsSource = people,
      ItemTemplate = new PersonDataTemplateSelector {
        ValidTemplate = validTemplate,
        InvalidTemplate = invalidTemplate }
    };

    Content = new StackLayout {
      Margin = new Thickness (20),
      Children = {
        ...
        listView
      }
    };
  }
  ...  
}

La instancia de PersonDataTemplateSelector establece sus propiedades ValidTemplate y InvalidTemplate en las instancias de DataTemplate correspondientes creadas por el método SetupDataTemplates.The PersonDataTemplateSelector instance sets its ValidTemplate and InvalidTemplate properties to the appropriate DataTemplate instances created by the SetupDataTemplates method. En tiempo de ejecución, ListView llama al método PersonDataTemplateSelector.OnSelectTemplate para cada uno de los elementos de la colección subyacente, y la llamada pasa el objeto de datos como el parámetro item.At runtime, the ListView calls the PersonDataTemplateSelector.OnSelectTemplate method for each of the items in the underlying collection, with the call passing the data object as the item parameter. Después, el elemento DataTemplate devuelto por el método se aplica a ese objeto.The DataTemplate that is returned by the method is then applied to that object.

ResumenSummary

En este artículo se ha explicado cómo crear y consumir un elemento DataTemplateSelector.This article has demonstrated how to create and consume a DataTemplateSelector. DataTemplateSelector se puede usar para elegir un elemento DataTemplate en tiempo de ejecución según el valor de una propiedad enlazada a datos.A DataTemplateSelector can be used to choose a DataTemplate at runtime based on the value of a data-bound property. Esto permite aplicar varias instancias de DataTemplate al mismo tipo de objeto para personalizar la apariencia de objetos concretos.This enables multiple DataTemplate instances to be applied to the same type of object, to customize the appearance of particular objects.