Criando um Xamarin.Forms DataTemplateSelector
Um DataTemplateSelector pode ser usado para escolher um DataTemplate em runtime com base no valor de uma propriedade associada a dados. Isso permite que várias instâncias de DataTemplates sejam aplicadas ao mesmo tipo de objeto, para personalizar a aparência de objetos específicos. Este artigo demonstra como criar e consumir um DataTemplateSelector.
Um seletor de modelo de dados permite cenários como uma associação do ListView
a uma coleção de objetos, em que a aparência de cada objeto no ListView
pode ser escolhida em runtime pelo seletor de modelo de dados que retorna um DataTemplate
específico.
Criando um DataTemplateSelector
Um seletor de modelo de dados é implementado criando uma classe herdada de DataTemplateSelector
. O método OnSelectTemplate
é substituído para retornar um determinado DataTemplate
, conforme mostrado no exemplo de código a seguir:
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;
}
}
O método OnSelectTemplate
retorna o modelo apropriado com base no valor da propriedade DateOfBirth
. O modelo a ser retornado é o valor da propriedade ValidTemplate
ou da propriedade InvalidTemplate
, que são definidas ao consumir o PersonDataTemplateSelector
.
Uma instância da classe de seletor de modelo de dados pode ser atribuída a Xamarin.Forms propriedades de controle, como ListView.ItemTemplate
. Para obter uma lista de propriedades válidas, confira Criando um DataTemplate.
Limitações
As instâncias DataTemplateSelector
têm as seguintes limitações:
- A subclasse
DataTemplateSelector
deve sempre retornar o mesmo modelo para os mesmos dados se consultada várias vezes. - A subclasse
DataTemplateSelector
não deve retornar outra subclasseDataTemplateSelector
. - A subclasse
DataTemplateSelector
não deve retornar novas instâncias de umDataTemplate
em cada chamada. Em vez disso, a mesma instância deve ser retornada. Não fazer isso criará uma perda de memória e desabilitará a virtualização. - No Android, não pode haver mais de 20 modelos de dados diferentes por
ListView
.
Consumindo um DataTemplateSelector em XAML
Em XAML, o PersonDataTemplateSelector
pode ser instanciado ao declará-lo como um recurso, conforme mostrado no exemplo de código a seguir:
<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>
Esse nível de página ResourceDictionary
define duas instâncias DataTemplate
e uma instância PersonDataTemplateSelector
. A instância PersonDataTemplateSelector
define suas propriedades ValidTemplate
e InvalidTemplate
como as instâncias DataTemplate
apropriadas usando a extensão de marcação StaticResource
. Observe que, embora os recursos sejam definidos no ResourceDictionary
da página, eles também podem ser definidos no nível de controle ou do aplicativo.
A instância PersonDataTemplateSelector
é consumida atribuindo-a à propriedade ListView.ItemTemplate
, conforme mostrado no exemplo de código a seguir:
<ListView x:Name="listView" ItemTemplate="{StaticResource personDataTemplateSelector}" />
Em runtime, o ListView
chama o método PersonDataTemplateSelector.OnSelectTemplate
para cada um dos itens na coleção subjacente, com a chamada passando o objeto de dados como o parâmetro item
. O DataTemplate
retornado pelo método é aplicado a esse objeto.
As capturas de tela a seguir mostram o resultado do ListView
aplicando o PersonDataTemplateSelector
a cada objeto na coleção subjacente:
Qualquer objeto Person
que tem o valor da propriedade DateOfBirth
maior que ou igual a 1980 é exibido em verde, com os objetos restantes sendo exibidos em vermelho.
Consumindo um DataTemplateSelector em C#
Em C#, o PersonDataTemplateSelector
pode ser instanciado e atribuído à propriedade ListView.ItemTemplate
, conforme mostrado no exemplo de código a seguir:
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
}
};
}
...
}
A instância PersonDataTemplateSelector
define suas propriedades ValidTemplate
e InvalidTemplate
como as instâncias DataTemplate
apropriadas pelo método SetupDataTemplates
. Em runtime, o ListView
chama o método PersonDataTemplateSelector.OnSelectTemplate
para cada um dos itens na coleção subjacente, com a chamada passando o objeto de dados como o parâmetro item
. O DataTemplate
retornado pelo método é aplicado a esse objeto.
Resumo
Este artigo demonstrou como criar e consumir um DataTemplateSelector
. Um DataTemplateSelector
pode ser usado para escolher um DataTemplate
em runtime com base no valor de uma propriedade associada a dados. Isso permite que várias instâncias de DataTemplate
sejam aplicadas ao mesmo tipo de objeto, para personalizar a aparência de objetos específicos.