Desenvolvimento

29 nov, 2017

Xamarin Forms – ListView: Usando HeaderTemplate e FooterTemplate para exibir dados

Publicidade

Neste artigo, mostrarei como podemos usar o header e footer do ListView para exibir informações e totalizações em aplicações Xamarin Forms, usando o Visual Studio 2017 e a linguagem C#.

A view ListView é uma das mais importantes views do Xamarin Forms e apresenta uma versatilidade fantástica que podemos aproveitar em nossas aplicações.

Vou criar uma agenda de contatos e exibir uma relação de contatos com nome e e-mail em um ListView, aproveitando para mostrar como exibir informações no Header e como exibir o total de contatos no Footer.

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 or Native)
  • Informe o nome XF_AgendaContatos e clique no botão OK
  • A seguir selecione Blank App e marque as opções – Xamarin.Forms e Portable Class Library (PCL) e clique em OK

 

Será criado um projeto contendo no projeto Portable as páginas App.xaml e MainPage.xaml.

No code-behind do arquivo App.xaml, temos a classe App.cs que irá conter o código compartilhado e que vamos usar neste artigo.

No arquivo App.cs, inclua o código a seguir onde definimos a página principal da aplicação como sendo a página MainPage:

using Xamarin.Forms;
namespace XF_RealmDB
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new NavigationPage(new XF_PclStorage.MainPage());
        }
        protected override void OnStart()
        {
            // Handle when your app starts
        }
        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }
        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Ao final, teremos as referências incluídas em todos os projetos da nossa solução. Iremos usar a página MainPage.xaml como página principal da nossa aplicação.

Definindo o Model e o Serviço

Vamos agora definir o nosso modelo de domínio e o serviço que preenche o modelo com algumas informações sobre contatos.

Criaremos uma pasta Model no projeto e o arquivo Contato.cs, definindo a classe Contato com o seguinte código:

 public class Contato
    {
        public string Nome { get; set; }
        public string Email { get; set; }
    }

A seguir, crie o arquivo ContatoService.cs e defina a classe ContatoService conforme o código mostrado a seguir:

using System.Collections.ObjectModel;
namespace XF_AgendaContatos.Model
{
    public class ContatoService
    {
          /// <summary>
          /// Obtém a lista com todos os contatos registrados.
          /// </summary>
	public ObservableCollection<Contato> TodosContatos { get; private set; }
        /// <summary>
        /// Inicializa uma instância dessa classe populando a lista de contatos.
        /// </summary>
        public ContatoService()
        {
            TodosContatos = new ObservableCollection<Contato> {
                new Contato { Nome = "Jose Macoratti", Email = "egestas@anequeNullam.co.uk" },
                new Contato { Nome = "Maria Julia", Email = "a.tortor@Sed.net" },
                new Contato { Nome = "Osmar Bueno", Email = "tristique@faucibusutnulla.net" },
                new Contato { Nome = "Yuri Lima", Email = "montes.nascetur.ridiculus@fringillaest.ca" },
                new Contato { Nome = "Leonardo Silveira", Email = "imperdiet.ullamcorper@Quisque.com" },
                new Contato { Nome = "Nadir Figueiredo", Email = "adipiscing@anteipsum.ca" },
                new Contato { Nome = "Emely Soares", Email = "aliquet.molestie.tellus@Nam.net" },
            };
        }
    }
}

Esta classe define uma lista de contatos que será a nossa fonte de dados usada no projeto. Note que estamos usando a coleção ObservableCollection() que implementa a interface INotifyPropertyChanged.

Definindo a ViewModel

Crie uma pasta ViewModel no projeto, e a seguir crie o arquivo ContatoListViewModel.cs nesta pasta, definindo o código abaixo na ViewModel ContatoListViewModel:

using System.Collections.Generic;
using System.Linq;
using XF_AgendaContatos.Model;
namespace XF_AgendaContatos.ViewModel
{
    public class ContatoListViewModel
    {
        //define a fonte do listview e a quantidade de itens a ser exibida no rodape
        public IList<Contato> Items { get; private set; }
        public int ItemsCount { get; private set; }
        //define o telefone a ser exibido na view (não existe no model)
        public string Telefone { get; private set; } = "+55 (11) 9807-0055";
        //construtor
        public ContatoListViewModel()
        {
            var repo = new ContatoService();
            Items = repo.TodosContatos.OrderBy(c => c.Nome).ToList();
            ItemsCount = repo.TodosContatos.Count;
        }
    }
}

Na ViewModel definimos a propriedade Items que representa a nossa lista de contatos, a propriedade ItemsCount que representa o total de itens da lista e a propriedade Telefone.

Observe que as propriedades ItemsCount e Telefone não existem no Model, elas foram definidas apenas na ViewModel para serem exibidas no rodapé e no cabeçalho.

Definindo a View: MainPage

Vamos agora definir o código da view MainPage.xaml conforme 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_AgendaContatos"
             BackgroundColor="Aquamarine"
             x:Class="XF_AgendaContatos.MainPage"
             Title="Agenda Contatos">
    <ListView
        x:Name="ContatosListView"
		ItemsSource="{Binding Items}" Header="{Binding}" Footer="{Binding}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell 
	         Text="{Binding Nome}" Detail="{Binding Email, StringFormat='E-mail: {0}'}" DetailColor="Blue"/>
            </DataTemplate>
        </ListView.ItemTemplate>

        <ListView.HeaderTemplate>
            <DataTemplate>
                <ContentView BackgroundColor="Beige">
                    <Label Margin="16" HorizontalOptions="CenterAndExpand" Text="{Binding Telefone, StringFormat='Meu Fone: {0}'}" />
                </ContentView>
            </DataTemplate>
        </ListView.HeaderTemplate>

        <ListView.FooterTemplate>
            <DataTemplate>
                <ContentView BackgroundColor="Beige">
                    <Label Margin="16"  HorizontalOptions="CenterAndExpand" Text="{Binding ItemsCount, StringFormat='Total de Contatos: {0}'}" />
                </ContentView>
            </DataTemplate>
        </ListView.FooterTemplate>
    </ListView>
</ContentPage>

No código, definimos o ListView e sua propriedade ItemsSource usando o databinding para a lista de contatos Items.

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 Telefone e ItemsCount.

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):

Conforme esperado, estamos exibindo o telefone no Header e o total de contatos no Footer.

Pegue o código do projeto aqui: XF_AgendaContatos.zip (sem as referências).