Xamarin Forms - Agrupando itens em uma ListView
Hoje veremos como podemos agrupar itens em uma view ListView no Xamarin Forms. |
Já escrevi alguns artigos sobre a ListView do Xamarin Forms. Se você esta chegando e quer saber mais sobre a ListView acompanhe esses meus artigos:
Hoje veremos como agrupar itens na view ListView do Xamarin Forms.
Vou implementar uma Agenda de Contatos onde iremos agrupar a lista pela letra inicial do nome do contato.
Então vamos à parte prática...
Recursos usados:
Criando o projeto no Visual Studio 2017 Community
Abra o Visual Studio Community 2017 e clique em New Project;
Selecione Visual C#, o template Cross Plataform e a seguir Cross Plataform App(Xamarin.Forms);
Informe o nome XF_Agenda e clique no botão OK;
A seguir selecione Blank App e marque as plataformas para quais deseja gerar os projetos;
Marque a opção Xamarin.Forms, e, em Code Sharing Strategy, marque .NET Standard, que substitui a opção de projetos PCL a partir do VS 2017 update 15.5.
Definindo o modelo de domínio e o repositório de dados
Crie uma pasta Models no projeto portátil via menu Project -> New Folder;
Na pasta Models crie a classe Contato que representa o nosso modelo de domínio, ou seja representa um contato:
public class
Contato { public string Nome { get; set; } public string Email { get; set; } public string Telefone { get; set; } } |
Ainda na pasta Models crie a classe ContatoRepository que representa o nosso repositório de dados onde vamos definir os dados usados na aplicação:
public class ContatoRepository
{
public IList<Contato> GetContatos { get; private set; }
public ContatoRepository()
{
GetContatos = new List<Contato> {
new Contato { Nome = "Alex Silveira", Email = "egestas@anequeNullam.co.uk", Telefone="9985-5623" },
new Contato { Nome = "Wilson Martin", Email = "a.tortor@Sed.net", Telefone="9985-5623" },
new Contato { Nome = "Osmar Moss", Email = "tristique@faucibusutnulla.net", Telefone="9985-5623" },
new Contato { Nome = "Yasmim Dudley", Email = "montes.nascetur.ridiculus@fringillaest.ca", Telefone="9985-5623" },
new Contato { Nome = "Yoshio Anthony", Email = "ut.aliquam.iaculis@pharetraNam.edu" , Telefone="9985-5623"},
new Contato { Nome = "Valentina Poole", Email = "auctor@consectetuer.org" , Telefone="9985-5623"},
new Contato { Nome = "Armando Tillman", Email = "facilisis.vitae.orci@liberolacusvarius.com" , Telefone="9985-5623"},
new Contato { Nome = "Klaus Hickman", Email = "Pellentesque.habitant@tristiqueaceleifend.org" , Telefone="9985-5623" },
new Contato { Nome = "Levi Marshall", Email = "imperdiet.ullamcorper@Quisque.com" , Telefone="9985-5623" },
new Contato { Nome = "Norberto Boone", Email = "adipiscing@anteipsum.ca" , Telefone="9985-5623" },
new Contato { Nome = "Emerlindo Mendez", Email = "aliquet.molestie.tellus@Nam.net" , Telefone="9985-5623" },
new Contato { Nome = "Marcos Compton", Email = "Etiam.bibendum.fermentum@malesuadaIntegerid.co.uk" , Telefone="9985-5623" },
new Contato { Nome = "Braulio Chapman", Email = "lacinia.orci@aliquetdiamSed.ca" , Telefone="9985-5623" },
new Contato { Nome = "Heleno Roberson", Email = "gravida@Nunc.edu" , Telefone="9985-5623" },
new Contato { Nome = "Yuri Herrera", Email = "velit@erat.org" , Telefone="9985-5623" },
new Contato { Nome = "Lucas Brown", Email = "magnis@Cumsociis.org" , Telefone="9985-5623" },
new Contato { Nome = "Gilson Reilly", Email = "vel@NullamenimSed.com" , Telefone="9985-5623" },
new Contato { Nome = "Arsenio Suarez", Email = "ridiculus.mus.Aenean@tellusfaucibusleo.co.uk" , Telefone="9985-5623" },
new Contato { Nome = "Igor Mclaughlin", Email = "ut.lacus.Nulla@Aliquamnec.edu" , Telefone="9985-3023" },
new Contato { Nome = "Carla Craft", Email = "Etiam.gravida.molestie@rutrummagna.ca" , Telefone="9985-3023" },
new Contato { Nome = "Benedito Carson", Email = "adipiscing@enimMauris.edu" , Telefone="9985-3023" },
new Contato { Nome = "Roberto Reynolds", Email = "commodo@sapienmolestie.edu" , Telefone="9985-3023" },
new Contato { Nome = "Rivaldo Mcguire", Email = "sem.elit.pharetra@nuncrisus.com" , Telefone="9985-3023" },
new Contato { Nome = "William Fuller", Email = "bibendum@ultrices.com" , Telefone="9985-3023" },
new Contato { Nome = "Helio Shaffer", Email = "lectus.pede@nisi.org" , Telefone="9985-2123" },
new Contato { Nome = "Armando Chapman", Email = "erat@Donecsollicitudin.edu" , Telefone="9985-2123" },
new Contato { Nome = "Josia Adams", Email = "justo.Praesent.luctus@purus.org" , Telefone="9985-2123" },
new Contato { Nome = "Denis Webb", Email = "sit.amet.consectetuer@Loremipsumdolor.org" , Telefone="9985-2123" },
new Contato { Nome = "Jacob Singleton", Email = "sem.consequat@vehiculaPellentesque.co.uk" , Telefone="9985-2123" },
new Contato { Nome = "Carina Tucker", Email = "molestie@erosturpis.ca" , Telefone="9985-2123" },
new Contato { Nome = "Felix Holder", Email = "sollicitudin.a@Curae.co.uk" , Telefone="9985-1123" },
new Contato { Nome = "Mateus Reid", Email = "Etiam.bibendum@Donecat.edu" , Telefone="9985-1123" },
new Contato { Nome = "Anabel Noel", Email = "rhoncus.Donec@vel.edu" , Telefone="9985-1123" },
new Contato { Nome = "Karina Dunlap", Email = "lectus@risusQuisque.co.uk" , Telefone="9985-1123" },
new Contato { Nome = "Silvio Ewing", Email = "cubilia@afeugiattellus.ca" , Telefone="9985-1123" },
new Contato { Nome = "Lucas Reed", Email = "id.risus@Aliquam.edu" , Telefone="9985-1123" },
new Contato { Nome = "Geraldo Huff", Email = "non.arcu.Vivamus@fames.edu" , Telefone="9985-0923" },
new Contato { Nome = "Fernando Carroll", Email = "ut.nisi.a@elit.edu" , Telefone="9985-0923" },
new Contato { Nome = "Leonardo Hamilton", Email = "vitae@penatibusetmagnis.net" , Telefone="9985-0923" },
new Contato { Nome = "Myles Knowles", Email = "vitae.aliquam@magna.org" , Telefone="9985-0923" },
new Contato { Nome = "Cristina Schmidt", Email = "imperdiet.dictum.magna@vitaeerat.org" , Telefone="9985-0923" },
new Contato { Nome = "Thais Ball", Email = "Cras.eu@ataugue.net" , Telefone="9985-0923" },
new Contato { Nome = "Renato Mclean", Email = "leo@vitaenibh.net" , Telefone="9985-2323" },
new Contato { Nome = "Celio Rogers", Email = "eros.turpis.non@ettristique.co.uk" , Telefone="9985-1023" },
new Contato { Nome = "Otavio Estes", Email = "vel@ac.edu" , Telefone="9985-7723"},
};
}
}
|
Definindo a ViewModel : ContatoListaViewModel
Crie uma pasta chamada ViewModels no projeto portátil e a seguir crie a classe ContatoListaViewModel que representa a lógica da nossa View:
public class ContatoListaViewModel
{
public IList<Contato> Items { get; private set; }
public int ItemsCount { get; private set; }
public string MeuNumero { get; set; } = "+55 (11) 1111-1111";
public ContatoListaViewModel()
{
var repo = new ContatoRepository();
Items = repo.GetContatos.OrderBy(c => c.Nome).ToList();
ItemsCount = repo.GetContatos.Count;
}
}
|
O código retorna a lista de contatos na propriedade Items , o total de contatos na propriedade ItemsCount e o número de telefone defininido em MenuNumero.
Definindo o código da página MainPage
Abra o arquivo MainPage.xaml e inclua o código abaixo:
<?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:local="clr-namespace:XF_Agenda"
x:Class="XF_Agenda.MainPage"
Title="Agenda">
<ListView x:Name="LvwContatos"
Margin="5"
ItemsSource="{Binding Items}"
Header="{Binding}"
Footer="{Binding}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Nome}" Detail="{Binding Email, StringFormat='E-mail: {0}'}"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.HeaderTemplate>
<DataTemplate>
<ContentView BackgroundColor="Beige">
<Label Margin="10" HorizontalOptions="CenterAndExpand" Text="{Binding MeuNumero, StringFormat='Meu número: {0}'}" TextColor="Black"/>
</ContentView>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<ContentView BackgroundColor="Aquamarine">
<Label Margin="10" HorizontalOptions="CenterAndExpand" Text="{Binding ItemsCount, StringFormat='Contatos : {0}'}" TextColor="Black"/>
</ContentView>
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
</ContentPage>
|
No código XAML definimos uma ListView onde a sua propriedade ItemsSource esta fazendo o databinding com a propriedade Items da nossa ViewModel ContatoListaViewModel.
Para exibir os contatos usamos um ItemTemplate e a célula TextCell :
Text - para exibir a primeira linha de texto em fonte maior;
Detail - para exibir uma segunda linha de texto em fonte menor;
Definimos também o Header e Footer usando a notação {Binding} sem definir um Source ou Path. Fazendo assim, o XAML entende que o objeto que será usado para o Binding será o mesmo do BindingContext atual. Como o ListView propaga esse objeto para os templates Header e Footer isso não é necessário.
A seguir, definimos o HeaderTemplate e FooterTemplate configurados para exibir as propriedades MeuNumero e ItemsCount.
Vamos agora implementar o código no arquivo MainPage.xaml.cs :
Abra o arquivo MainPage.xaml.cs criado no projeto e a seguir defina o código abaixo:
using Xamarin.Forms;
using XF_AgendaContatos.ViewModel;
namespace XF_AgendaContatos
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new ContatoListViewModel();
}
}
}
|
No código estamos criando uma instância da nossa ViewModel e atribuindo ao BindingContext.
Executando o projeto iremos obter o seguinte resultado: (Nosso projeto padrão é o projeto Android)
Muito bem...
Agora vamos agrupar as informações da nossa Agenda de forma a organizar os nomes pela primeira letra do nome.
Agrupando as informações da Agenda
Para poder agrupar as informações da nossa agenda primeiro vamos temos que habilitar o nosso ListView a aceitar o agrupamento definindo as seguintes propriedades:
no arquivo MainPage.xaml :
...
<ListView x:Name="LvwContatos"
Margin="5"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key}"
ItemsSource="{Binding Items}"
Header="{Binding}"
Footer="{Binding}"
HasUnevenRows="True">
...
|
Após isso vamos alterar o código da nossa ViewModel ContatoListaViewModel definindo o código para agrupar as informações com base na primeira letra do nome:
public class ContatoListaViewModel
{
public IList<Contato> Items { get; private set; }
public List<ObservableGroupCollection<string,Contato>> DadosAgrupados { get; set; }
public int ItemsCount { get; private set; }
public string MeuNumero { get; set; } = "+55 (11) 1111-1111";
public ContatoListaViewModel()
{
var repo = new ContatoRepository();
Items = repo.GetContatos.OrderBy(c => c.Nome).ToList();
DadosAgrupados = Items.OrderBy(p => p.Nome)
.GroupBy(p => p.Nome[0].ToString())
.Select(p => new ObservableGroupCollection<string, Contato>(p)).ToList();
ItemsCount = repo.GetContatos.Count;
}
}
|
Definimos uma nova propriedade chamada DadosAgrupados() que é do tipo List<ObservableGroupCollection<string,Contato>> onde estamos ordenando os nomes pela primeira letra do nome.
Para dar suporte à implementação da propriedade precisamos criar a classe ObservableGroupCollection na pasta ViewModels:
public class ObservableGroupCollection<S, T> : ObservableCollection<T>
{
private readonly S _key;
public ObservableGroupCollection(IGrouping<S, T> group)
: base(group)
{
_key = group.Key;
}
public S Key
{
get { return _key; }
}
}
|
Essa classe herda de ObservableCollection permitindo assim, adicionar ou remover itens de um grupo existente, ela também define a primeira letra para realizar o agrupamento.
Para o nosso exemplo Key será do tipo string e a coleção será do tipo IEnumerable<Contato>.
Agora basta alterar a propriedade ItemsSource do ListView para a nova propriedade DadosAgrupados:
<ListView x:Name="LvwContatos"
Margin="5"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key}"
ItemsSource="{Binding DadosAgrupados}"
Header="{Binding}"
Footer="{Binding}"
HasUnevenRows="True">
Executando o projeto iremos obter o seguinte resultado :
Vemos agora as informações da agenda agrupadas em ordem alfabética pela primeira letra do nome.
Pegue o código usado no projeto aqui : XF_Agenda.zip (somente o projeto compartilhado)
Antes, como ministros
de Deus, tornando-nos recomendáveis em tudo; na muita paciência, nas aflições,
nas necessidades, nas angústias,Como contristados, mas sempre alegres; como
pobres, mas enriquecendo a muitos; como nada tendo, e possuindo tudo.
2
Coríntios 6:4,10
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
Xamarin Forms - Criando uma página de pequisa - Macoratti.net
Xamarin.Forms - Acessando a base de filmes do ... - Macoratti.net