Xamarin.Forms Dados CollectionView

CollectionView Inclui as seguintes propriedades que definem os dados a serem exibidos e sua aparência:

  • ItemsSource, do tipo IEnumerable, especifica a coleção de itens a serem exibidos e tem um valor padrão de null.
  • 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.

Observação

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 associações compiladas podem ser habilitadas para melhorar o desempenho da associação de dados em Xamarin.Forms aplicativos. Para obter mais informações, confira Associações compiladas do Xamarin.Forms.

Para obter informações sobre como alterar o CollectionView layout, consulte Xamarin.Forms 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 a associação de dados, consulte Xamarin.Forms Associaçã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.Children.Add(image);
    grid.Children.Add(nameLabel, 1, 0);
    grid.Children.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; }
}

As capturas de tela a seguir mostram o resultado da modelagem de cada item na lista:

Captura de tela de CollectionView onde cada item é modelado, no iOS e Android

Para obter mais informações sobre modelos de dados, consulte Xamarin.Forms 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 propriedades AmericanMonkey e OtherMonkey DataTemplate que são configuradas para diferentes modelos de dados. 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:

Captura de tela da seleção do modelo de item de runtime CollectionView, no iOS e no Android

Para obter mais informações sobre seletores de modelo de dados, consulte Criar um Xamarin.Forms 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 = Color.White };
    // ...

    SwipeView swipeView = new SwipeView();
    SwipeItem favoriteSwipeItem = new SwipeItem
    {
        Text = "Favorite",
        IconImageSource = "favorite.png",
        BackgroundColor = Color.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 = Color.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:

Captura de tela dos itens do menu de contexto CollectionView, no iOS e no Android

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 SwipeView controle, consulte Xamarin.Forms 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:

Captura de tela do CollectionView pull-to-refresh, no iOS e Android

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 RefreshViewo , consulte Xamarin.Forms 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.

CollectionView define as seguintes propriedades para controlar o carregamento incremental de dados:

  • RemainingItemsThreshold, do tipo int, o limite de itens ainda não visíveis na lista na qual o evento RemainingItemsThresholdReached será acionado.
  • RemainingItemsThresholdReachedCommand, do tipo ICommand, que é executado quando o RemainingItemsThreshold é alcançado.
  • RemainingItemsThresholdReachedCommandParameter, do tipo object, que é o parâmetro passado para RemainingItemsThresholdReachedCommand.

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.