Neste artigo vou apresentar o novo recurso CollectionView da versão 4.0 do Xamarin Forms. |
O Xamarin.Forms vem evoluindo e melhorando a cada nova versão, e, com a versão 4.0 temos muitas novidades. Hoje vou apresentar o recurso CollectionView.
Para este artigo estamos usando os seguintes recursos:
Para criar o projeto usado neste artigo no VS 2019 Community veja este link: Criar projeto Xamarin.Forms no VS 2019
A CollectionView é uma view para apresentar listas de dados usando diferentes especificações de layout. O objetivo é fornecer uma alternativa mais flexível e eficiente ao ListView.
Este recurso esta disponível a partir da versão 4.0, e, quando escrevi este artigo, estava em modo experimental. Para poder usar a CollectionView teremos que adicionar o código abaixo ás classes AppDelegate no iOS, e, MainActivity no Android, antes da chamada de Forms.Init:
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental"); |
Embora sejam similares, cabe destacar as seguintes diferenças da CollectionView para o ListView:
A CollectionView possui um modelo de layout flexível, que permite que os dados sejam apresentados na vertical ou na horizontal, em uma lista ou grade;
A CollectionView suporta seleção única e múltipla;
A CollectionView não tem conceito de células. Em vez disso, um modelo de dados é usado para definir a aparência de cada item de dados na lista.
A CollectionView usa automaticamente a virtualização fornecida pelos controles nativos subjacentes.
A CollectionView reduz a superfície da API do ListView. Muitas propriedades e eventos do ListView não estão presentes no CollectionView.
A CollectionView não inclui separadores internos.
Uma mudança que cabe destacar é que a CollectionView não possui o ViewCell oque melhora muito o desempenho.
Se você desejar migrar a ListView para a CollectionView pode consultar o roteiro na documentação oficial neste link: https://docs.microsoft.com/pt-br/xamarin/xamarin-forms/user-interface/collectionview/introduction
Como a CollectionView trabalha com dados ?
A CollectionView possui as seguintes propriedades que definem os dados a serem exibidos e a sua aparência:
Essas propriedades têm o respaldo dos objetos BindableProperty, o que significa que as propriedades podem ser alvo de vinculações de dados.
Assim, uma CollectionView é preenchida com dados, definindo sua propriedade ItemsSource para qualquer coleção que implemente IEnumerable.
Num exemplo bem simples podemos adicionar itens na CollectionView via código XAML, inicializando a propriedade ItemsSource de um array de strings :
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="XF_CollectinViewBasico.MainPage">
<CollectionView>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Santos</x:String>
<x:String>Palmeiras</x:String>
<x:String>Flamengo</x:String>
<x:String>Atlético-MG</x:String>
<x:String>São Paulo</x:String>
<x:String>Internacional</x:String>
<x:String>Atlético-PR</x:String>
</x:Array>
</CollectionView.ItemsSource>
</CollectionView>
</ContentPage>
|
Observe que o elemento x:Array requer um atributo Type que indica o tipo dos itens no array.
Se a
CollectionView precisar ser atualizada à medida que
os itens são adicionados, removidos ou alterados na coleção subjacente, a
coleção subjacente deve ser uma coleção IEnumerable
que envia notificações de alteração de propriedade como uma
ObservableCollection.
Por padrão, a CollectionView exibe itens em uma lista
vertical, conforme mostrado no resultado acima.
Fazendo o Data binding
Uma
CollectionView pode ser preenchida com dados usando o data binding ou associação
de dados, e associar sua propriedade ItemsSource a uma coleção
IEnumerable. No código XAML, isso é feito com a
marcação de extensão : Binding
<CollectionView ItemsSource="{Binding Times}" />
Neste exemplo, a propriedade ItemsSource vincula dados para a propriedade Times da viewmodel vinculada.
A aparência de cada item na CollectionView pode ser definida ao configurar a propriedade CollectionView.ItemTemplate para um DataTemplate.
Vejamos um exemplo prático desse comportamento.
Vamos criar um projeto com o nome XF_CollectinViewBasico seguindo as orientações deste artigo: Criar projeto Xamarin.Forms no VS 2019
No projeto criado vamos criar duas pastas : Models e ViewModels.
Na pasta Models vamos definir a classe Time:
public class Time
{
public string Nome { get; set; }
public string ImagemUrl { get; set; }
public int Pontos { get; set; }
public string Detalhes { get; set; }
}
|
Na pasta ViewModels vamos criar a classe TimesViewModel com o código a seguir:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Forms;
using XF_CollectinViewBasico.Models;
namespace XF_CollectinViewBasico.ViewModels
{
public class TimesViewModel : INotifyPropertyChanged
{
readonly IList<Time> source;
Time selectedTime;
int selectionCount = 1;
public ObservableCollection<Time> Times { get; private set; }
public IList<Time> EmptyTimes { get; private set; }
public Time SelectedTime
{
get
{
return selectedTime;
}
set
{
if (selectedTime != value)
{
selectedTime = value;
}
}
}
ObservableCollection<object> selectedTimes;
public ObservableCollection<object> SelectedTimes
{
get
{
return selectedTimes;
}
set
{
if (selectedTimes != value)
{
selectedTimes = value;
}
}
}
public string SelectedTimeMessage { get; private set; }
public ICommand FilterCommand => new Command<string>(FilterItems);
public ICommand TimeSelectionChangedCommand => new Command(TimeSelectionChanged);
public TimesViewModel()
{
source = new List<Time>();
CreateTimeCollection();
selectedTime = Times.Skip(3).FirstOrDefault();
TimeSelectionChanged();
SelectedTimes = new ObservableCollection<object>()
{
Times[1], Times[3], Times[4]
};
}
void CreateTimeCollection()
{
source.Add(new Time
{
Nome = "Santos",
ImagemUrl = "santos64.jpg",
Pontos = 29,
Detalhes = "Peixe - O time do Péle e da Vila Belmiro"
});
source.Add(new Time
{
Nome = "Palmeiras",
ImagemUrl = "palmeiras.jpg",
Pontos = 27,
Detalhes = "Porco - O alviverde paulista"
});
source.Add(new Time
{
Nome = "Flamengo",
ImagemUrl = "flamengo64.jpg",
Pontos = 24,
Detalhes = "Urubu - O rubro-nego carioca"
});
source.Add(new Time
{
Nome = "Atlético-MG",
ImagemUrl = "atleticomg.jpg",
Pontos = 21,
Detalhes = "Galo - O alvi-negro mineiro "
});
source.Add(new Time
{
Nome = "São Paulo",
ImagemUrl = "saopaulo64.jpg",
Pontos = 21,
Detalhes = "São Bento - São Paulo "
});
source.Add(new Time
{
Nome = "Internacional",
ImagemUrl = "internacional.jpg",
Pontos = 20,
Detalhes = "Rio Grande do sul "
});
source.Add(new Time
{
Nome = "Atlético-PR",
ImagemUrl = "atleticopr.jpg",
Pontos = 19,
Detalhes = "Paraná"
});
source.Add(new Time
{
Nome = "Corintians",
ImagemUrl = "corintians64.jpg",
Pontos = 19,
Detalhes = "São Jorge - São Paulo"
});
source.Add(new Time
{
Nome = "Goiás",
ImagemUrl = "goias.jpg",
Pontos = 17,
Detalhes = "Goiás"
});
source.Add(new Time
{
Nome = "Botafogo",
ImagemUrl = "botafogo.jpg",
Pontos = 16,
Detalhes = "Rio de Janeiro"
});
Times = new ObservableCollection<Time>(source);
}
void FilterItems(string filter)
{
var itensfiltrados = source.Where(time => time.Nome.ToLower().Contains(filter.ToLower())).ToList();
foreach (var time in source)
{
if (!itensfiltrados.Contains(time))
{
Times.Remove(time);
}
else
{
if (!Times.Contains(time))
{
Times.Add(time);
}
}
}
}
void TimeSelectionChanged()
{
SelectedTimeMessage = $"Time {selectionCount}: {SelectedTime.Nome}";
OnPropertyChanged("SelectedTimeMessage");
selectionCount++;
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
|
No código acima definimos algumas propriedades e definimos os dados que iremos usar para popular a CollectionView.
A seguir, ainda no projeto Android, vamos incluir as imagens dos escudos dos times, listadas a seguir, na pasta /Resources/drawable que iremos usar no projeto.
As imagens
podem ser obtidas no site:
https://aimore.org/escudos/geral.html
Implementando um layout
básico : lista vertical
No arquivo MainPage.xaml vamos incluir o código abaixo que vai usar a CollectionView e definir um leiaute de lista vertical que é o padrão.
Aqui estamos usando um grid e fazendo o data binding com a ViewModel TimesViewModel e as propriedades : Nome, ImagemUrl e Pontos:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="XF_CollectinViewBasico.MainPage">
<StackLayout Margin="5">
<CollectionView ItemsSource="{Binding Times}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="8">
<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 ImagemUrl}"
Aspect="AspectFill"
HeightRequest="40"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Nome}"
FontSize="Large"
TextColor="Blue"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Pontos}"
FontAttributes="Bold"
FontSize="Large"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
|
Observe que a CollectionView é muito parecida com a ListView possuindo o DataTemplate e a propriedade ItemsSource.
Agora abra o arquivo MainPage.xaml.cs e inclua o código abaixo:
using System.ComponentModel;
using Xamarin.Forms;
using XF_CollectinViewBasico.ViewModels;
namespace XF_CollectinViewBasico
{
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new TimesViewModel();
}
}
}
|
Estamos criando uma instância de TimesViewModel e fazendo o binding com o BindingContext:
Executando o projeto iremos obter o seguinte resultado:
Na próxima parte do artigo vamos continuar a abordar outros recursos da CollectionView.
Pegue o código do projeto compartilhado aqui : XF_CollectinViewBasico.zip (sem as referências)
"Pensai nas coisas que são de cima, e não nas que são
da terra;"
Colossenses 3:2
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
Xamarim - Desenvolvimento Multiplataforma com C# ... - Macoratti.net
Xamarin.Forms - Olá Mundo - Criando sua primeira ... - Macoratti.net
Xamarin.Forms - Olá Mundo - Anatomia da aplicação - Macoratti.net
https://developer.xamarin.com/api/type/Android.Widget.ListView/
https://developer.xamarin.com/api/property/Android.Widget.ListView.Adapter/
https://developer.xamarin.com/guides/xamarin-forms/user-interface/animation/