Resumo do Capítulo 19. Exibições de coleção
Observação
Este livro foi publicado na primavera de 2016, e não foi atualizado desde então. Há muito no livro que permanece valioso, mas parte do material está desatualizado, e alguns tópicos não estão mais totalmente corretos ou concluídos.
Xamarin.Forms define três exibições que mantêm coleções e exibem seus elementos:
Picker
é uma lista relativamente curta de itens de cadeia de caracteres que permite que o usuário escolha umListView
geralmente é uma longa lista de itens geralmente do mesmo tipo e formatação, permitindo também que o usuário escolha umTableView
é uma coleção de células (geralmente de vários tipos e aparências) para exibir dados ou gerenciar a entrada do usuário
É comum que aplicativos MVVM usem o ListView
para exibir uma coleção selecionável de objetos.
Opções de programa com o Seletor
O Picker
é uma boa opção quando você precisa permitir que o usuário escolha uma opção entre uma lista relativamente curta de string
itens.
O seletor e a manipulação de eventos
O exemplo PickerDemo demonstra como usar XAML para definir a Picker
Title
propriedade e adicionar string
itens à Items
coleção. Quando o usuário seleciona o Picker
, ele exibe os itens na Items
coleção de maneira dependente da plataforma.
O SelectedIndexChanged
evento indica quando o usuário selecionou um item. Em seguida, a propriedade baseada em SelectedIndex
zero indica o item selecionado. Se nenhum item for selecionado, SelectedIndex
será igual a –1.
Você também pode usar SelectedIndex
para inicializar o item selecionado, mas ele deve ser definido após o preenchimento da Items
coleção. No XAML, isso significa que você provavelmente usará um elemento de propriedade para definir SelectedIndex
.
Associação de dados ao Seletor
A SelectedIndex
propriedade é apoiada por uma propriedade associável, mas Items
não é, portanto, o uso da associação de dados com um Picker
é difícil. Uma solução é usar o Picker
em combinação com um ObjectToIndexConverter
, como o da Xamarin.Formsbiblioteca Book.Toolkit . O PickerBinding demonstra como isso funciona.
Observação
O Xamarin.FormsPicker
agora inclui ItemsSource
propriedades e SelectedItem
que dão suporte à associação de dados. Consulte Seletor.
Renderizando dados com ListView
O ListView
é a única classe derivada da ItemsView<TVisual>
qual herda as ItemsSource
propriedades e ItemTemplate
.
ItemsSource
é do tipo IEnumerable
, mas é null
por padrão e deve ser inicializado explicitamente ou (mais comumente) definido como uma coleção por meio de uma associação de dados. Os itens desta coleção podem ser de qualquer tipo.
ListView
define uma SelectedItem
propriedade que é definida como um dos itens da ItemsSource
coleção ou null
se nenhum item está selecionado. ListView
aciona o ItemSelected
evento quando um novo item é selecionado.
Coleções e seleções
O exemplo ListViewList preenche um ListView
com 17 Color
valores em uma List<Color>
coleção. Os itens são selecionáveis, mas, por padrão, são exibidos com suas representações pouco atraentes ToString
. Vários exemplos neste capítulo mostram como corrigir essa exibição e torná-la tão atraente quanto desejado.
O separador de linha
Em telas iOS e Android, uma linha fina separa as linhas. Você pode controlar isso com as SeparatorVisibility
propriedades e SeparatorColor
. SeparatorVisibility
é do tipo SeparatorVisibility
, uma enumeração com dois membros:
Associação de dados ao item selecionado
A SelectedItem
propriedade é apoiada por uma propriedade associável, portanto, pode ser a origem ou o destino de uma associação de dados. Seu padrão BindingMode
é OneWayToSource
, mas geralmente é o destino de uma associação de dados bidirecional, especialmente em cenários MVVM. O exemplo ListViewArray demonstra esse tipo de associação.
A diferença de ObservableCollection
O exemplo ListViewLogger define a ItemsSource
propriedade de um ListView
para uma List<DateTime>
coleção e, em seguida, adiciona progressivamente um novo DateTime
objeto à coleção a cada segundo usando um temporizador.
No entanto, o ListView
não se atualiza automaticamente porque a List<T>
coleção não tem um mecanismo de notificação para indicar quando os itens são adicionados ou removidos da coleção.
Uma classe muito melhor a ser usada nesses cenários é ObservableCollection<T>
definida no System.Collections.ObjectModel
namespace. Essa classe implementa a INotifyCollectionChanged
interface e, consequentemente, aciona um CollectionChanged
evento quando os itens são adicionados ou removidos da coleção ou quando são substituídos ou movidos dentro da coleção. Quando o ListView
detecta internamente que uma classe que implementa INotifyCollectionChanged
foi definida como sua ItemsSource
propriedade, ela anexa um manipulador ao CollectionChanged
evento e atualiza sua exibição quando a coleção é alterada.
O exemplo ObservableLogger demonstra o uso de ObservableCollection
.
Modelos e células
Por padrão, um ListView
exibe itens em sua coleção usando o método de ToString
cada item. Uma abordagem melhor envolve a definição de um modelo para exibir os itens.
Para experimentar esse recurso, você pode usar a NamedColor
classe na Xamarin.Formsbiblioteca Book.Toolkit . Essa classe define uma propriedade estática All
do tipo IList<NamedColor>
que contém 141 NamedColor
objetos correspondentes aos campos públicos da Color
estrutura.
O exemplo NaiveNamedColorList define o ItemsSource
de um ListView
para essa NamedColor.All
propriedade, mas apenas os nomes de classe totalmente qualificados dos NamedColor
objetos são exibidos.
ListView
precisa de um modelo para exibir esses itens. No código, você pode definir a ItemTemplate
propriedade definida por para ItemsView<TVisual>
um DataTemplate
objeto usando o DataTemplate
construtor que faz referência a um derivado da Cell
classe . Cell
tem cinco derivativos:
TextCell
— contém duasLabel
exibições (conceitualmente falando)ImageCell
— adiciona uma exibiçãoImage
aTextCell
EntryCell
— contém uma exibiçãoEntry
com umLabel
SwitchCell
— contém umSwitch
com umLabel
ViewCell
— pode ser qualquerView
(provavelmente com filhos)
Em seguida, chame SetValue
e SetBinding
no DataTemplate
objeto para associar valores às Cell
propriedades ou para definir associações de dados nas Cell
propriedades que fazem referência às propriedades dos itens na ItemsSource
coleção. Isso é demonstrado no exemplo TextCellListCode .
Como cada item é exibido pelo ListView
, uma pequena árvore visual é construída a partir do modelo e as associações de dados são estabelecidas entre o item e as propriedades dos elementos nesta árvore visual. Você pode ter uma ideia desse processo instalando manipuladores para os ItemAppearing
eventos e ItemDisappearing
do ListView
ou usando um construtor alternativo DataTemplate
que usa uma função que é chamada sempre que a árvore visual de um item deve ser criada.
O TextCellListXaml mostra um programa funcionalmente idêntico inteiramente em XAML. Uma DataTemplate
marca é definida como a ItemTemplate
propriedade do ListView
e, em seguida, o TextCell
é definido como .DataTemplate
As associações às propriedades dos itens na coleção são definidas diretamente nas Text
propriedades e Detail
do TextCell
.
Células personalizadas
No XAML, é possível definir um ViewCell
como DataTemplate
e, em seguida, definir uma árvore visual personalizada como a View
propriedade de ViewCell
. (View
é a propriedade de conteúdo de para ViewCell
que as ViewCell.View
marcas não sejam necessárias.) O exemplo CustomNamedColorList demonstra essa técnica:
lista de cores nomeada personalizada da
Obter o dimensionamento certo para todas as plataformas pode ser complicado. A RowHeight
propriedade é útil, mas em alguns casos você vai querer recorrer à HasUnevenRows
propriedade , que é menos eficiente, mas força o ListView
para dimensionar as linhas. Para iOS e Android, você deve usar uma dessas duas propriedades para obter o dimensionamento de linha adequado.
Agrupando os itens listview
ListView
dá suporte ao agrupamento de itens e à navegação entre esses grupos. A ItemsSource
propriedade deve ser definida como uma coleção de coleções: o objeto definido ItemsSource
como deve implementar IEnumerable
e cada item na coleção também deve implementar IEnumerable
. Cada grupo deve incluir duas propriedades: uma descrição de texto do grupo e uma abreviação de três letras.
A NamedColorGroup
classe na Xamarin.Formsbiblioteca Book.Toolkit cria sete grupos de NamedColor
objetos. O exemplo ColorGroupList mostra como usar esses grupos com a IsGroupingEnabled
propriedade de ListView
definido como true
e as GroupDisplayBinding
propriedades e GroupShortNameBinding
associadas às propriedades em cada grupo.
Cabeçalhos de grupo personalizados
É possível criar cabeçalhos personalizados para os ListView
grupos substituindo a GroupDisplayBinding
propriedade GroupHeaderTemplate
pela definição de um modelo para os cabeçalhos.
ListView e interatividade
Geralmente, um aplicativo obtém interação do usuário com um ListView
anexando um manipulador ao ItemSelected
evento ou ItemTapped
ou definindo uma associação de dados na SelectedItem
propriedade . Mas alguns tipos de célula (EntryCell
e SwitchCell
) permitem a interação do usuário e também é possível criar células personalizadas que interagem com o usuário. O InteractiveListView cria 100 instâncias de ColorViewModel
e permite que o usuário altere cada cor usando um trio de Slider
elementos. O programa também usa o ColorToContrastColorConverter
no Xamarin.FormsBook.Toolkit.
ListView e MVVM
ListView
desempenha um grande papel em cenários MVVM. Sempre que uma coleção IEnumerable
existe em um ViewModel, ela geralmente é associada a um ListView
. Além disso, os itens na coleção geralmente implementam INotifyPropertyChanged
para associar com propriedades em um modelo.
Uma coleção de ViewModels
Para explorar isso, a biblioteca SchoolOfFineArts cria várias classes com base em um arquivo de dados XML e imagens de alunos fictícios nesta escola fictícia.
A classe Student
deriva de ViewModelBase
. A StudentBody
classe é uma coleção de Student
objetos e também deriva de ViewModelBase
. O SchoolViewModel
baixa o arquivo XML e monta todos os objetos.
O programa StudentList usa um ImageCell
para exibir os alunos e suas imagens em um ListView
:
O exemplo ListViewHeader adiciona uma Header
propriedade, mas ela só aparece no Android.
Seleção e o contexto de associação
O programa SelectedStudentDetail associa o BindingContext
de um StackLayout
à SelectedItem
propriedade do ListView
. Isso permite que o programa exiba informações detalhadas sobre o aluno selecionado.
Menus de contexto
Uma célula pode definir um menu de contexto que é implementado de maneira específica da plataforma. Para criar esse menu, adicione MenuItem
objetos à ContextActions
propriedade do Cell
.
MenuItem
define cinco propriedades:
Text
do tipostring
Icon
do tipoFileImageSource
IsDestructive
do tipobool
Command
do tipoICommand
CommandParameter
do tipoobject
As Command
propriedades e CommandParameter
implicam que o ViewModel para cada item contém métodos para executar os comandos de menu desejados. Em cenários não MVVM, MenuItem
também define um Clicked
evento.
CellContextMenu demonstra essa técnica. A Command
propriedade de cada MenuItem
um está associada a uma propriedade do tipo ICommand
na Student
classe . Defina a IsDestructive
propriedade true
como para um MenuItem
que remove ou exclui o objeto selecionado.
Variando os visuais
Às vezes, você desejará pequenas variações nos visuais dos itens no com base em ListView
uma propriedade . Por exemplo, quando a média do ponto de nota de um aluno fica abaixo de 2,0, o exemplo ColorCodedStudents exibe o nome desse aluno em vermelho.
Isso é feito por meio do uso de um conversor de valor de associação, ThresholdToObjectConverter
, na Xamarin.Formsbiblioteca Book.Toolkit .
Atualizando o conteúdo
O ListView
dá suporte a um gesto de pull-down para atualizar seus dados. O programa deve definir a IsPullToRefresh
propriedade como true
para habilitar isso. O ListView
responde ao gesto de pull-down definindo sua IsRefreshing
propriedade true
como e acionando o Refreshing
evento e (para cenários MVVM) chamando o Execute
método de sua RefreshCommand
propriedade.
O código que manipula o Refresh
evento ou, RefreshCommand
em seguida, possivelmente atualiza os dados exibidos pelo ListView
e define IsRefreshing
de volta para false
.
O exemplo RssFeed demonstra o uso de um RssFeedViewModel
que implementa RefreshCommand
e IsRefreshing
propriedades para associação de dados.
O TableView e suas intenções
Embora o ListView
geralmente exiba várias instâncias do mesmo tipo, o TableView
geralmente se concentra em fornecer uma interface do usuário para várias propriedades de vários tipos. Cada item é associado a seu próprio Cell
derivado para exibir a propriedade ou fornecer uma interface do usuário para ele.
Propriedades e hierarquias
TableView
define apenas quatro propriedades:
Intent
do tipoTableIntent
, uma enumeraçãoRoot
do tipoTableRoot
, a propriedade de conteúdo deTableView
RowHeight
do tipoint
HasUnevenRows
do tipobool
A TableIntent
enumeração indica como você pretende usar o TableView
:
Esses membros também sugerem alguns usos para o TableView
.
Várias outras classes estão envolvidas na definição de uma tabela:
TableSectionBase
é uma classe abstrata que deriva deBindableObject
e define umaTitle
propriedadeTableSectionBase<T>
é uma classe abstrata que deriva deTableSectionBase
e implementaIList<T>
eINotifyCollectionChanged
TableSection
deriva deTableSectionBase<Cell>
TableRoot
deriva deTableSectionBase<TableSection>
Em suma, TableView
tem uma Root
propriedade que você define como um TableRoot
objeto, que é uma coleção de TableSection
objetos, cada um deles uma coleção de Cell
objetos. Uma tabela tem várias seções e cada seção tem várias células. A tabela em si pode ter um título e cada seção pode ter um título. Embora TableView
faça uso de Cell
derivados, ele não faz uso de DataTemplate
.
Uma forma prosaica
O exemplo EntryForm define um PersonalInformation
modelo de exibição, uma instância da qual se torna o BindingContext
TableView
do . Cada Cell
derivado em seu TableSection
pode ter associações às propriedades da PersonalInformation
classe .
Células personalizadas
O exemplo ConditionalCells se expande em EntryForm. A ProgrammerInformation
classe inclui uma propriedade booliana que rege a aplicabilidade de duas propriedades adicionais. Para essas duas propriedades adicionais, o programa usa um personalizado PickerCell
com base em um PickerCell.xaml e PickerCell.xaml.cs na Xamarin.Formsbiblioteca Book.Toolkit .
Embora as IsEnabled
propriedades dos dois PickerCell
elementos estejam associadas à propriedade booliana no ProgrammerInformation
, essa técnica não parece funcionar, o que solicita o próximo exemplo.
Seções condicionais
O exemplo ConditionalSection coloca os dois itens condicionais na seleção do item booliano em um separado TableSection
. O arquivo code-behind remove esta seção do ou o TableView
adiciona de volta com base na propriedade Boolean.
Um menu TableView
Outro uso de um TableView
é um menu. O exemplo MenuCommands demonstra um menu que permite que você se mova um pouco BoxView
pela tela.