Compartilhar via


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 completos.

Xamarin.Forms define três modos de exibição que mantêm coleções e exibem seus elementos:

  • Picker é uma lista relativamente curta de itens de cadeia de caracteres que permite ao usuário escolher um
  • ListView é muitas vezes uma longa lista de itens geralmente do mesmo tipo e formatação, também permitindo que o usuário escolha um
  • TableViewé 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 os 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 escolha 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 aTitlePickerpropriedade e adicionar string itens à Items coleção. Quando o usuário seleciona o Picker, ele exibe os itens na coleção de maneira dependente da Items plataforma.

O SelectedIndexChanged evento indica quando o usuário selecionou um item. 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 depois que a Items coleção for preenchida. Em XAML, isso significa que você provavelmente usará um elemento de propriedade para definir SelectedIndex.

Vinculação de dados ao Seletor

A SelectedIndex propriedade é apoiada por uma propriedade vinculável, mas Items não é, portanto, usar a vinculação de dados com um Picker é difícil. Uma solução é usar o Picker em combinação com um ObjectToIndexConverter tal na Xamarin.Formsbiblioteca Book.Toolkit. O PickerBinding demonstra como isso funciona.

Observação

O Xamarin.FormsPicker now inclui ItemsSource e SelectedItem propriedades que oferecem suporte à vinculação de dados. Consulte Selecionador.

Renderizando dados com ListView

O ListView é a única classe que deriva da ItemsView<TVisual> qual ele herda as ItemsSource propriedades e ItemTemplate .

ItemsSource é do tipo IEnumerable , mas é null por padrão e deve ser explicitamente inicializado ou (mais comumente) definido para 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 na ItemsSource coleção ou null se nenhum item for selecionado. ListView dispara 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 eles 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:

Vinculação de dados do item selecionado

A SelectedItem propriedade é apoiada por uma propriedade vinculá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 ObservableCollection

O exemplo ListViewLogger define a ItemsSource propriedade de a 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 para usar em tais cenários é ObservableCollection<T> definida no System.Collections.ObjectModel namespace. Essa classe implementa a INotifyCollectionChanged interface e, consequentemente, dispara 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 implementação de classe INotifyCollectionChanged foi definida para sua ItemsSource propriedade, ele anexa um manipulador ao CollectionChanged evento e atualiza sua exibição quando a coleção é alterada.

O exemplo ObservableLogger demonstra o uso do 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 NamedColorXamarin.Formsclasse na biblioteca 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 a ListView para essa NamedColor.All propriedade, mas somente 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 ItemsView<TVisual> para um DataTemplate objeto usando o DataTemplate construtor que faz referência a Cell uma derivada da classe. Cell tem cinco derivados:

  • TextCell — contém dois Label pontos de vista (conceitualmente falando)
  • ImageCell — adiciona uma Image vista a TextCell
  • EntryCell — contém uma Entry vista com um Label
  • SwitchCell — contém um Switch com um Label
  • ViewCell — pode ser qualquer View (provavelmente com crianças)

Em seguida, chame SetValue e SetBinding ligue o 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.

À medida que cada item é exibido pelo ListView, uma pequena árvore visual é construída a partir do modelo, e associações de dados são estabelecidas entre o item e as propriedades dos elementos nessa árvore visual. Você pode ter uma ideia desse processo instalando manipuladores para os ItemAppearing e ItemDisappearing eventos do , ou usando um construtor alternativoDataTemplateque usa uma função que é chamada cada vez que a ListViewárvore visual de um item deve ser criada.

O TextCellListXaml mostra um programa funcionalmente idêntico inteiramente em XAML. Uma DataTemplate tag é definida como a ItemTemplate propriedade do ListView, e, em seguida, o TextCell é definido como o DataTemplate. As ligações às propriedades dos itens na coleção são definidas diretamente nas Text propriedades e Detail do TextCell.

Células personalizadas

Em XAML, é possível definir a ViewCell para o DataTemplate e, em seguida, definir uma árvore visual personalizada como a View propriedade de ViewCell. View( é a propriedade content de ViewCell para que as ViewCell.View tags não sejam necessárias.) O exemplo CustomNamedColorList demonstra esta técnica:

Captura de tela tripla da Lista de Cores Nomeadas Personalizadas

Conseguir 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 tamanho das linhas. Para iOS e Android, você deve usar uma dessas duas propriedades para obter o dimensionamento de linha adequado.

Agrupando os itens ListView

ListView Suporta o agrupamento de itens e a 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 abreviatura 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 set como truee as GroupDisplayBinding propriedades e GroupShortNameBinding vinculadas às propriedades em cada grupo.

Cabeçalhos de grupo personalizados

É possível criar cabeçalhos personalizados para os ListView grupos substituindo a GroupDisplayBinding propriedade pela GroupHeaderTemplate 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 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 faz uso do ColorToContrastColorConverter no Xamarin.FormsBook.Toolkit.

ListView e MVVM

ListView desempenha um papel importante em cenários MVVM. Sempre que uma IEnumerable coleção existe em um ViewModel, ela geralmente é vinculada a um ListViewarquivo . Além disso, os itens na coleção geralmente são implementados INotifyPropertyChanged para vincular com propriedades em um modelo.

Uma coleção de ViewModels

Para explorar isso, a biblioteca SchoolOfFineArts cria várias classes baseadas em um arquivo de dados XML e imagens de alunos fictícios dessa 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:

Captura de tela tripla da Lista de Estudantes

O exemplo ListViewHeader adiciona uma Header propriedade, mas ela só aparece no Android.

Seleção e contexto de vinculação

O programa SelectedStudentDetail vincula o BindingContext de a 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 uma maneira específica da plataforma. Para criar esse menu, adicione MenuItem objetos à ContextActions propriedade do Cell.

MenuItem define cinco propriedades:

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.

O CellContextMenu demonstra essa técnica. A Command propriedade de cada MenuItem um está vinculada a uma propriedade do tipo ICommand na Student classe. Defina a IsDestructive propriedade como true para um MenuItem que remove ou exclui o objeto selecionado.

Variando o visual

Às vezes, você vai querer pequenas variações nos visuais dos itens no baseado em ListView uma propriedade. Por exemplo, quando a média de notas 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 valores de vinculação, ThresholdToObjectConverter, na Xamarin.Formsbiblioteca Book.Toolkit.

Atualizando o conteúdo

O suporta um gesto ListView suspenso para atualizar seus dados. O programa deve definir a IsPullToRefresh propriedade para true habilitar isso. O ListView responde ao gesto suspenso definindo sua IsRefreshing propriedade como true, e aumentando 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 o RefreshCommand então 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 e IsRefreshing propriedades para associação de RefreshCommand dados.

O TableView e suas intenções

Enquanto o ListView geralmente exibe várias instâncias do mesmo tipo, o é geralmente focado TableView em fornecer uma interface do usuário para várias propriedades de vários tipos. Cada item é associado à sua própria Cell derivada para exibir a propriedade ou fornecer uma interface de usuário para ela.

Propriedades e hierarquias

TableView define apenas quatro propriedades:

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 de BindableObject e define uma Title propriedade

  • TableSectionBase<T> é uma classe abstrata que deriva de TableSectionBase e implementa IList<T> e INotifyCollectionChanged

  • TableSection deriva de TableSectionBase<Cell>

  • TableRoot deriva de TableSectionBase<TableSection>

Em resumo, TableView tem uma Root propriedade que você define como um TableRoot objeto, que é uma coleção de TableSection objetos, cada um dos quais é 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 derivativos, não faz uso de DataTemplate.

Uma forma prosaica

O exemplo EntryForm define um PersonalInformation modelo de exibição, cuja instância se torna a BindingContext do TableView. Cada Cell derivada em sua TableSection pode então ter ligações às propriedades da PersonalInformation classe.

Células personalizadas

O exemplo ConditionalCells se expande em EntryForm. A ProgrammerInformation classe inclui uma propriedade booleana que controla a aplicabilidade de duas propriedades adicionais. Para essas duas propriedades adicionais, o programa usa um personalizado PickerCell baseado em um PickerCell.xaml e PickerCell.xaml.cs na Xamarin.Formsbiblioteca Book.Toolkit.

Embora as IsEnabled propriedades dos dois PickerCell elementos estejam ligadas à propriedade booleana no ProgrammerInformation, essa técnica parece não funcionar, o que solicita a próxima amostra.

Seções condicionais

O exemplo ConditionalSection coloca os dois itens que são condicionais à seleção do item booleano em um TableSectionarquivo separado. O arquivo code-behind remove essa seção do TableView ou a adiciona novamente 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.