Preencher um CollectionView com dados
A UI do aplicativo multiplataforma .NET (.NET MAUI) CollectionView inclui as seguintes propriedades que definem os dados a serem exibidos e sua aparência:
ItemsSource
, do tipoIEnumerable
, especifica a coleção de itens a serem exibidos e tem um valor padrão denull
.ItemTemplate
, do tipo DataTemplate, especifica o modelo a ser aplicado a cada item na coleção de itens a serem exibidos.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que as propriedades podem ser alvos de vinculações de dados.
CollectionView define uma propriedade ItemsUpdatingScrollMode
que representa o comportamento de rolagem do CollectionView quando novos itens são adicionados a ele. Para obter mais informações sobre essa propriedade, veja Controlar a posição de rolagem quando novos itens são adicionados.
CollectionView oferece suporte à virtualização incremental de dados à medida que o usuário rola. Para obter mais informações, veja Carregar dados de forma incremental.
Preencher um CollectionView com dados
Um CollectionView é preenchido com dados definindo sua propriedade ItemsSource
para qualquer coleção que implemente IEnumerable
. Por padrão, CollectionView exibe itens em uma lista vertical.
Importante
Se o CollectionView for necessário para atualizar conforme os itens são adicionados, removidos ou alterados na coleção subjacente, a coleção subjacente deverá ser uma coleção IEnumerable
que envia notificações de alteração de propriedade, como ObservableCollection
.
CollectionView pode ser preenchido com dados usando vinculação de dados para vincular sua propriedade ItemsSource
a uma coleção IEnumerable
. No XAML, isso é conseguido com a extensão de marcação Binding
:
<CollectionView ItemsSource="{Binding Monkeys}" />
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
Nesse exemplo, os dados da propriedade ItemsSource
são vinculados à propriedade Monkeys
do viewmodel conectado.
Observação
As vinculações compiladas podem ser habilitadas para melhorar o desempenho da vinculação de dados em aplicativos .NET MAUI. Para obter mais informações, confira Associações compiladas.
Para obter informações sobre como alterar o CollectionView layout, veja Especificar o layout CollectionView. Para obter informações sobre como definir a aparência de cada item no CollectionView, veja Definir aparência do item. Para obter mais informações sobre vinculação de dados, veja Vinculação de dados.
Aviso
CollectionView lançará uma exceção se seu ItemsSource
for atualizado no thread da UI.
Definir a aparência do item
A aparência de cada item no CollectionView pode ser definida definindo a propriedade CollectionView.ItemTemplate
como um DataTemplate:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.ItemTemplate = new DataTemplate(() =>
{
Grid grid = new Grid { Padding = 10 };
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
Image image = new Image { Aspect = Aspect.AspectFill, HeightRequest = 60, WidthRequest = 60 };
image.SetBinding(Image.SourceProperty, "ImageUrl");
Label nameLabel = new Label { FontAttributes = FontAttributes.Bold };
nameLabel.SetBinding(Label.TextProperty, "Name");
Label locationLabel = new Label { FontAttributes = FontAttributes.Italic, VerticalOptions = LayoutOptions.End };
locationLabel.SetBinding(Label.TextProperty, "Location");
Grid.SetRowSpan(image, 2);
grid.Add(image);
grid.Add(nameLabel, 1, 0);
grid.Add(locationLabel, 1, 1);
return grid;
});
Os elementos especificados no DataTemplate definem a aparência de cada item da lista. No exemplo, o layout dentro do DataTemplate é gerenciado por um Grid. O Grid contém um objeto Image e dois objetos Label, todos vinculados às propriedades da classe Monkey
:
public class Monkey
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
A captura de tela a seguir mostra o resultado da modelagem de cada item da lista:
Dica
Colocar um CollectionView dentro de um VerticalStackLayout pode interromper a rolagem do CollectionView e limitar o número de itens exibidos. Nessa situação, substitua o VerticalStackLayout por um Grid.
Para obter mais informações sobre modelos de dados, consulte Modelos de dados.
Escolher a aparência do item em tempo de execução
A aparência de cada item no CollectionView pode ser escolhida em tempo de execução, com base no valor do item, definindo a propriedade CollectionView.ItemTemplate
como um objeto DataTemplateSelector:
<ContentPage ...
xmlns:controls="clr-namespace:CollectionViewDemos.Controls">
<ContentPage.Resources>
<DataTemplate x:Key="AmericanMonkeyTemplate">
...
</DataTemplate>
<DataTemplate x:Key="OtherMonkeyTemplate">
...
</DataTemplate>
<controls:MonkeyDataTemplateSelector x:Key="MonkeySelector"
AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
</ContentPage.Resources>
<CollectionView ItemsSource="{Binding Monkeys}"
ItemTemplate="{StaticResource MonkeySelector}" />
</ContentPage>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
ItemTemplate = new MonkeyDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
A propriedade ItemTemplate
é definida como um objeto MonkeyDataTemplateSelector
. O exemplo a seguir mostra a classe MonkeyDataTemplateSelector
:
public class MonkeyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate AmericanMonkey { get; set; }
public DataTemplate OtherMonkey { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
}
}
A classe MonkeyDataTemplateSelector
define as propriedades AmericanMonkey
e OtherMonkey
DataTemplate que são definidas para modelos de dados diferentes. A substituição OnSelectTemplate
retorna o modeloAmericanMonkey
, que exibe o nome e a localização do macaco em azul-petróleo, quando o nome do macaco contém "América". Quando o nome do macaco não contém "América", a substituição OnSelectTemplate
retorna o modelo OtherMonkey
, que exibe o nome e a localização do macaco em prata:
Para obter mais informações sobre seletores de modelo de dados, consulte Criar um DataTemplateSelector.
Importante
Ao usar CollectionView, nunca defina o elemento raiz dos seus objetos DataTemplate como um ViewCell. Isso resultará no lançamento de uma exceção porque CollectionView não tem conceito de células.
Menus de contexto
CollectionView oferece suporte a menus de contexto para itens de dados por meio do SwipeView, que revela o menu de contexto com um gesto de deslizar. O SwipeView é um controle de contêiner que envolve um item de conteúdo e fornece itens de menu de contexto para esse item de conteúdo. Portanto, os menus de contexto são implementados para um CollectionView criando um SwipeView que define o conteúdo que o SwipeView envolve e os itens do menu de contexto que são revelados pelo gesto de deslizar. Isso é conseguido definindo SwipeView como a visualização raiz no DataTemplate que define a aparência de cada item de dados no CollectionView:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem Text="Favorite"
IconImageSource="favorite.png"
BackgroundColor="LightGreen"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}"
CommandParameter="{Binding}" />
<SwipeItem Text="Delete"
IconImageSource="delete.png"
BackgroundColor="LightPink"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid BackgroundColor="White"
Padding="10">
<!-- Define item appearance -->
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.ItemTemplate = new DataTemplate(() =>
{
// Define item appearance
Grid grid = new Grid { Padding = 10, BackgroundColor = Colors.White };
// ...
SwipeView swipeView = new SwipeView();
SwipeItem favoriteSwipeItem = new SwipeItem
{
Text = "Favorite",
IconImageSource = "favorite.png",
BackgroundColor = Colors.LightGreen
};
favoriteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.FavoriteCommand", source: collectionView));
favoriteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");
SwipeItem deleteSwipeItem = new SwipeItem
{
Text = "Delete",
IconImageSource = "delete.png",
BackgroundColor = Colors.LightPink
};
deleteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.DeleteCommand", source: collectionView));
deleteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");
swipeView.LeftItems = new SwipeItems { favoriteSwipeItem, deleteSwipeItem };
swipeView.Content = grid;
return swipeView;
});
Nesse exemplo, o SwipeView conteúdo é um Grid que define a aparência de cada item no CollectionView. Os itens de deslizar são usados para executar ações no conteúdo SwipeView e são revelados quando o controle é deslizado do lado esquerdo:
SwipeView suporta quatro direções de deslizamento diferentes, com a direção de deslizamento sendo definida pela coleção direcional SwipeItems
à qual os objetos SwipeItems
são adicionados. Por padrão, um item de deslizar é executado quando o usuário toca nele. Além disso, depois que um item de deslizar for executado, os itens de deslizar serão ocultados e o conteúdo SwipeView será exibido novamente. No entanto, esses comportamentos podem ser alterados.
Para obter mais informações sobre o controle SwipeView, veja SwipeView.
Deslizar para atualizar
CollectionView suporta a funcionalidade pull to refresh por meio do RefreshView, que permite que os dados exibidos sejam atualizados puxando para baixo a lista de itens. O RefreshView é um controle de contêiner que fornece funcionalidade pull para atualizar para seu filho, desde que o filho suporte conteúdo rolável. Portanto, puxar para atualizar é implementado para um CollectionView definindo-o como filho de um RefreshView:
<RefreshView IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}">
<CollectionView ItemsSource="{Binding Animals}">
...
</CollectionView>
</RefreshView>
Este é o código C# equivalente:
RefreshView refreshView = new RefreshView();
ICommand refreshCommand = new Command(() =>
{
// IsRefreshing is true
// Refresh data here
refreshView.IsRefreshing = false;
});
refreshView.Command = refreshCommand;
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
refreshView.Content = collectionView;
// ...
Quando o usuário inicia uma atualização, o ICommand definido pela propriedade Command
é executado, o que deve atualizar os itens que estão sendo exibidos. Uma visualização de atualização é mostrada enquanto a atualização ocorre, que consiste em um círculo de progresso animado:
O valor da propriedade RefreshView.IsRefreshing
indica o estado atual do RefreshView. Quando uma atualização é acionada pelo usuário, essa propriedade fará a transição automaticamente para true
. Assim que a atualização for concluída, você deverá redefinir a propriedade para false
.
Para obter mais informações sobre RefreshView, veja RefreshView.
Carregar dados de forma incremental
CollectionView oferece suporte à virtualização incremental de dados à medida que o usuário rola. Isso permite cenários como o carregamento assíncrono de uma página de dados de um serviço Web, à medida que o usuário rola. Além disso, o ponto em que mais dados são carregados é configurável para que os usuários não vejam espaços em branco ou sejam impedidos de rolar.
Aviso
Não tente carregar dados de forma incremental em um CollectionView que esteja em um StackLayout. Esse cenário fará com que ocorra um loop infinito onde o CollectionView continuará se expandindo.
CollectionView define as seguintes propriedades para controlar o carregamento incremental de dados:
RemainingItemsThreshold
, do tipoint
, o limite de itens ainda não visíveis na lista na qual o eventoRemainingItemsThresholdReached
será acionado.RemainingItemsThresholdReachedCommand
, do tipo ICommand, que é executado quando oRemainingItemsThreshold
é alcançado.RemainingItemsThresholdReachedCommandParameter
, do tipoobject
, que é o parâmetro passado paraRemainingItemsThresholdReachedCommand
.
CollectionView também define um evento RemainingItemsThresholdReached
que é acionado quando o CollectionView é rolado o suficiente para que RemainingItemsThreshold
os itens não sejam exibidos. Esse evento pode ser tratado para carregar mais itens. Além disso, quando o evento RemainingItemsThresholdReached
é disparado, o RemainingItemsThresholdReachedCommand
é executado, permitindo que o carregamento incremental de dados ocorra em um viewmodel.
O valor padrão da propriedade RemainingItemsThreshold
é -1, o que indica que o evento RemainingItemsThresholdReached
nunca será acionado. Quando o valor da propriedade for 0, o evento RemainingItemsThresholdReached
será acionado quando o item final do ItemsSource
for exibido. Para valores maiores que 0, o evento RemainingItemsThresholdReached
será disparado quando o ItemsSource
contiver aquele número de itens ainda não rolados.
Observação
CollectionView valida a propriedade RemainingItemsThreshold
para que seu valor seja sempre maior ou igual a -1.
O exemplo XAML a seguir mostra um CollectionView que carrega dados de forma incremental:
<CollectionView ItemsSource="{Binding Animals}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReached="OnCollectionViewRemainingItemsThresholdReached">
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
RemainingItemsThreshold = 5
};
collectionView.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
Nesse exemplo de código, o evento RemainingItemsThresholdReached
é acionado quando há 5 itens ainda não rolados e, em resposta, executa o manipulador de eventos OnCollectionViewRemainingItemsThresholdReached
:
void OnCollectionViewRemainingItemsThresholdReached(object sender, EventArgs e)
{
// Retrieve more data here and add it to the CollectionView's ItemsSource collection.
}
Observação
Os dados também podem ser carregados de forma incremental vinculando o RemainingItemsThresholdReachedCommand
a uma implementação ICommand no viewmodel.