Riepilogo del capitolo 19. Viste raccolta
Nota
Questo libro è stato pubblicato nella primavera del 2016, e non è stato aggiornato da allora. C'è molto nel libro che rimane prezioso, ma alcuni materiali sono obsoleti, e alcuni argomenti non sono più completamente corretti o completi.
Xamarin.Forms definisce tre visualizzazioni che mantengono le raccolte e visualizzano i relativi elementi:
Picker
è un elenco relativamente breve di elementi stringa che consente all'utente di sceglierne unoListView
è spesso un lungo elenco di elementi di solito dello stesso tipo e formattazione, consentendo anche all'utente di sceglierne unoTableView
è una raccolta di celle (in genere di vari tipi e aspetto) per visualizzare i dati o gestire l'input dell'utente
È comune che le applicazioni MVVM usino ListView
per visualizzare una raccolta selezionabile di oggetti.
Opzioni del programma con Selezione
è Picker
una buona scelta quando è necessario consentire all'utente di scegliere un'opzione tra un elenco relativamente breve di string
elementi.
Selezione e gestione degli eventi
L'esempio PickerDemo illustra come usare XAML per impostare la Picker
Title
proprietà e aggiungere string
elementi alla Items
raccolta. Quando l'utente seleziona , Picker
visualizza gli elementi nella Items
raccolta in modo dipendente dalla piattaforma.
L'evento SelectedIndexChanged
indica quando l'utente ha selezionato un elemento. La proprietà in base SelectedIndex
zero indica quindi l'elemento selezionato. Se non è selezionato alcun elemento, SelectedIndex
è uguale a –1.
È anche possibile usare SelectedIndex
per inizializzare l'elemento selezionato, ma deve essere impostato dopo la compilazione della Items
raccolta. In XAML questo significa che probabilmente userai un elemento della proprietà per impostare SelectedIndex
.
Data binding della selezione
La SelectedIndex
proprietà è supportata da una proprietà associabile ma Items
non è , pertanto l'uso del data binding con un Picker
è difficile. Una soluzione consiste nell'usare l'oggetto Picker
in combinazione con uno ObjectToIndexConverter
come quello nella Xamarin.Formslibreria Book.Toolkit . PickerBinding illustra il funzionamento di questa operazione.
Nota
Include Xamarin.FormsPicker
ora ItemsSource
le proprietà e SelectedItem
che supportano il data binding. Vedere Selezione.
Rendering dei dati con ListView
ListView
è l'unica classe che deriva da ItemsView<TVisual>
cui eredita le ItemsSource
proprietà e ItemTemplate
.
ItemsSource
è di tipo IEnumerable
, ma è null
per impostazione predefinita e deve essere inizializzato in modo esplicito o (più comunemente) impostato su una raccolta tramite un data binding. Gli elementi di questa raccolta possono essere di qualsiasi tipo.
ListView
definisce una SelectedItem
proprietà impostata su uno degli elementi dell'insieme ItemsSource
o null
se non è selezionato alcun elemento. ListView
genera l'evento ItemSelected
quando viene selezionato un nuovo elemento.
Raccolte e selezioni
L'esempio ListViewList riempie un oggetto ListView
con 17 Color
valori in una List<Color>
raccolta. Gli elementi sono selezionabili, ma per impostazione predefinita vengono visualizzati con le relative rappresentazioni inattive ToString
. Diversi esempi in questo capitolo illustrano come correggere la visualizzazione e renderla attraente come desiderato.
Separatore di riga
In iOS e Android viene visualizzata una linea sottile che separa le righe. È possibile controllare questa proprietà con le SeparatorVisibility
proprietà e SeparatorColor
. SeparatorVisibility
la proprietà è di tipo SeparatorVisibility
, un'enumerazione con due membri:
Data binding dell'elemento selezionato
La SelectedItem
proprietà è supportata da una proprietà associabile, pertanto può essere l'origine o la destinazione di un data binding. Il valore predefinito BindingMode
è OneWayToSource
, ma in genere è la destinazione di un data binding bidirezionale, in particolare negli scenari MVVM. L'esempio ListViewArray illustra questo tipo di associazione.
Differenza observableCollection
L'esempio ListViewLogger imposta la ItemsSource
proprietà di un ListView
oggetto a un List<DateTime>
insieme e quindi aggiunge progressivamente un nuovo DateTime
oggetto all'insieme ogni secondo usando un timer.
Tuttavia, l'oggetto ListView
non viene aggiornato automaticamente perché la List<T>
raccolta non dispone di un meccanismo di notifica per indicare quando gli elementi vengono aggiunti o rimossi dalla raccolta.
Una classe molto migliore da usare in questi scenari è ObservableCollection<T>
definita nello spazio dei System.Collections.ObjectModel
nomi . Questa classe implementa l'interfaccia INotifyCollectionChanged
e di conseguenza genera un CollectionChanged
evento quando gli elementi vengono aggiunti o rimossi dalla raccolta oppure quando vengono sostituiti o spostati all'interno della raccolta. Quando rileva ListView
internamente che una classe che implementa INotifyCollectionChanged
è stata impostata sulla relativa ItemsSource
proprietà, associa un gestore all'evento e ne aggiorna la CollectionChanged
visualizzazione quando la raccolta cambia.
L'esempio ObservableLogger illustra l'uso di ObservableCollection
.
Modelli e celle
Per impostazione predefinita, un ListView
oggetto visualizza gli elementi nella raccolta utilizzando il metodo di ToString
ogni elemento. Un approccio migliore prevede la definizione di un modello per visualizzare gli elementi.
Per sperimentare questa funzionalità, è possibile usare la NamedColor
classe nella Xamarin.Formslibreria Book.Toolkit. Questa classe definisce una proprietà statica All
di tipo IList<NamedColor>
che contiene 141 NamedColor
oggetti corrispondenti ai campi pubblici della Color
struttura.
L'esempio NaiveNamedColorList imposta l'oggetto ItemsSource
di una ListView
su questa NamedColor.All
proprietà, ma vengono visualizzati solo i nomi di classe completi degli NamedColor
oggetti.
ListView
richiede un modello per visualizzare questi elementi. Nel codice è possibile impostare la ItemTemplate
proprietà definita da ItemsView<TVisual>
su un DataTemplate
oggetto usando il DataTemplate
costruttore che fa riferimento a una derivata della Cell
classe . Cell
ha cinque derivati:
TextCell
— contiene dueLabel
visualizzazioni (concettualmente parlando)ImageCell
— aggiunge unaImage
visualizzazione aTextCell
EntryCell
— contiene unaEntry
visualizzazione con unLabel
SwitchCell
— contiene un oggetto con unSwitch
oggettoLabel
ViewCell
— può essere qualsiasiView
(probabilmente con figli)
Chiamare quindi e SetBinding
sull'oggetto DataTemplate
per associare i valori alle Cell
proprietà oppure per impostare i data binding sulle Cell
proprietà che fanno riferimento alle proprietà degli elementi dell'insiemeItemsSource
.SetValue
Questo è illustrato nell'esempio TextCellListCode .
Quando ogni elemento viene visualizzato da ListView
, viene costruito un piccolo albero visivo dal modello e i data binding vengono stabiliti tra l'elemento e le proprietà degli elementi in questa struttura ad albero visuale. È possibile ottenere un'idea di questo processo installando gestori per gli ItemAppearing
eventi e ItemDisappearing
di ListView
oppure usando un costruttore alternativo DataTemplate
che usa una funzione chiamata ogni volta che è necessario creare un albero visivo di un elemento.
TextCellListXaml mostra un programma completamente identico a livello funzionale in XAML. Un DataTemplate
tag viene impostato sulla ItemTemplate
proprietà dell'oggetto ListView
e quindi TextCell
viene impostato su DataTemplate
. Le associazioni alle proprietà degli elementi dell'insieme vengono impostate direttamente sulle Text
proprietà e Detail
di TextCell
.
Celle personalizzate
In XAML è possibile impostare un ViewCell
oggetto su DataTemplate
e quindi definire una struttura ad albero visuale personalizzata come View
proprietà di ViewCell
. (View
è la proprietà del contenuto di ViewCell
in modo che i ViewCell.View
tag non siano necessari. L'esempio CustomNamedColorList illustra questa tecnica:
Ottenere il ridimensionamento giusto per tutte le piattaforme può essere complicato. La RowHeight
proprietà è utile, ma in alcuni casi si vuole ricorrere alla HasUnevenRows
proprietà , che è meno efficiente ma forza le ListView
dimensioni delle righe. Per iOS e Android, è necessario usare una di queste due proprietà per ottenere il ridimensionamento corretto delle righe.
Raggruppamento degli elementi listView
ListView
supporta il raggruppamento di elementi e lo spostamento tra tali gruppi. La ItemsSource
proprietà deve essere impostata su un insieme di raccolte: l'oggetto ItemsSource
impostato su deve implementare IEnumerable
e ogni elemento dell'insieme deve implementare IEnumerable
anche . Ogni gruppo deve includere due proprietà: una descrizione testuale del gruppo e un'abbreviazione di tre lettere.
La NamedColorGroup
classe nella Xamarin.Formslibreria Book.Toolkit crea sette gruppi di NamedColor
oggetti. Nell'esempio ColorGroupList viene illustrato come usare questi gruppi con la IsGroupingEnabled
proprietà impostata ListView
su true
e le GroupDisplayBinding
proprietà e GroupShortNameBinding
associate alle proprietà in ogni gruppo.
Intestazioni di gruppo personalizzate
È possibile creare intestazioni personalizzate per i ListView
gruppi sostituendo la GroupDisplayBinding
proprietà con la GroupHeaderTemplate
definizione di un modello per le intestazioni.
ListView e interattività
In genere un'applicazione ottiene l'interazione dell'utente con un ListView
oggetto associando un gestore all'evento ItemSelected
o ItemTapped
o impostando un data binding sulla SelectedItem
proprietà . Tuttavia, alcuni tipi di cella (EntryCell
e SwitchCell
) consentono l'interazione dell'utente ed è anche possibile creare celle personalizzate che interagiscono con l'utente. InteractiveListView crea 100 istanze di e consente all'utente di ColorViewModel
modificare ogni colore usando un trio di Slider
elementi. Il programma usa ColorToContrastColorConverter
anche in Xamarin.FormsBook.Toolkit.
ListView e MVVM
ListView
svolge un ruolo importante negli scenari MVVM. Ogni volta che esiste una IEnumerable
raccolta in un oggetto ViewModel, viene spesso associata a un oggetto ListView
. Inoltre, gli elementi nella raccolta spesso implementano INotifyPropertyChanged
per l'associazione con le proprietà in un modello.
Raccolta di ViewModels
Per esplorarlo, la libreria SchoolOfFineArts crea diverse classi basate su un file di dati XML e immagini di studenti fittizi in questa scuola fittizia.
La classe Student
deriva da ViewModelBase
. La StudentBody
classe è una raccolta di Student
oggetti e deriva anche da ViewModelBase
. SchoolViewModel
Scarica il file XML e assembla tutti gli oggetti.
Il programma StudentList usa un oggetto ImageCell
per visualizzare gli studenti e le relative immagini in un ListView
oggetto :
L'esempio ListViewHeader aggiunge una Header
proprietà, ma viene visualizzata solo in Android.
Selezione e contesto di associazione
Il programma SelectedStudentDetail associa l'oggetto BindingContext
di a StackLayout
alla SelectedItem
proprietà dell'oggetto ListView
. Ciò consente al programma di visualizzare informazioni dettagliate sullo studente selezionato.
Menu di scelta rapida
Una cella può definire un menu di scelta rapida implementato in modo specifico della piattaforma. Per creare questo menu, aggiungere MenuItem
oggetti alla ContextActions
proprietà dell'oggetto Cell
.
MenuItem
definisce cinque proprietà:
Text
di tipostring
Icon
di tipoFileImageSource
IsDestructive
di tipobool
Command
di tipoICommand
CommandParameter
di tipoobject
Le Command
proprietà e CommandParameter
implicano che ViewModel per ogni elemento contiene metodi per eseguire i comandi di menu desiderati. Negli scenari non MVVM definisce MenuItem
anche un Clicked
evento.
CellContextMenu illustra questa tecnica. La Command
proprietà di ogni MenuItem
oggetto è associata a una proprietà di tipo ICommand
nella Student
classe . Impostare la IsDestructive
proprietà su true
per un oggetto MenuItem
che rimuove o elimina l'oggetto selezionato.
Variabile degli oggetti visivi
In alcuni casi si desiderano lievi variazioni negli oggetti visivi degli elementi nell'oggetto ListView
in base a una proprietà . Ad esempio, quando la media dei punti di grado di uno studente scende al di sotto di 2,0, l'esempio ColorCodedStudents visualizza il nome dello studente in rosso.
Questa operazione viene eseguita tramite l'uso di un convertitore di valori di associazione, ThresholdToObjectConverter
, nella Xamarin.Formslibreria Book.Toolkit.
Aggiornamento del contenuto
ListView
supporta un movimento di trascinamento verso il basso per aggiornare i dati. Il programma deve impostare la IsPullToRefresh
proprietà su true
per abilitare questa impostazione. Risponde ListView
al movimento di trascinamento verso il basso impostando la relativa IsRefreshing
proprietà su true
e generando l'evento Refreshing
e (per gli scenari MVVM) chiamando il Execute
metodo della relativa RefreshCommand
proprietà.
Il codice che gestisce l'evento Refresh
o RefreshCommand
quindi aggiorna eventualmente i dati visualizzati da ListView
e imposta IsRefreshing
nuovamente su false
.
L'esempio RssFeed illustra l'uso di un oggetto RssFeedViewModel
che implementa RefreshCommand
e IsRefreshing
proprietà per il data binding.
TableView e le relative finalità
Mentre in ListView
genere visualizza più istanze dello stesso tipo, l'oggetto TableView
è in genere incentrato sulla fornitura di un'interfaccia utente per più proprietà di vari tipi. Ogni elemento è associato al proprio Cell
derivato per visualizzare la proprietà o fornire un'interfaccia utente.
Proprietà e gerarchie
TableView
definisce solo quattro proprietà:
Intent
di tipoTableIntent
, un'enumerazioneRoot
di tipoTableRoot
, la proprietà content diTableView
RowHeight
di tipoint
HasUnevenRows
di tipobool
L'enumerazione TableIntent
indica come si intende usare :TableView
Questi membri suggeriscono anche alcuni usi per .TableView
Sono coinvolte diverse altre classi nella definizione di una tabella:
TableSectionBase
è una classe astratta che deriva daBindableObject
e definisce unaTitle
proprietàTableSectionBase<T>
è una classe astratta che deriva daTableSectionBase
e implementaIList<T>
eINotifyCollectionChanged
TableSection
deriva daTableSectionBase<Cell>
TableRoot
deriva daTableSectionBase<TableSection>
In breve, TableView
ha una Root
proprietà impostata su un TableRoot
oggetto , ovvero una raccolta di TableSection
oggetti, ognuno dei quali è una raccolta di Cell
oggetti . Una tabella include più sezioni e ogni sezione contiene più celle. La tabella stessa può avere un titolo e ogni sezione può avere un titolo. Sebbene TableView
usi Cell
derivati, non fa uso di DataTemplate
.
Forma prosaica
L'esempio EntryForm definisce un PersonalInformation
modello di visualizzazione, un'istanza di che diventa di TableView
BindingContext
. Ogni Cell
derivato nel relativo TableSection
può quindi avere associazioni alle proprietà della PersonalInformation
classe .
Celle personalizzate
L'esempio ConditionalCells si espande su EntryForm. La ProgrammerInformation
classe include una proprietà booleana che regola l'applicabilità di due proprietà aggiuntive. Per queste due proprietà aggiuntive, il programma usa un oggetto personalizzato PickerCell
basato su pickerCell.xaml e PickerCell.xaml.cs nella Xamarin.Formslibreria Book.Toolkit.
Anche se le IsEnabled
proprietà dei due PickerCell
elementi sono associate alla proprietà booleana in ProgrammerInformation
, questa tecnica non sembra funzionare, che richiede l'esempio successivo.
Sezioni condizionali
L'esempio ConditionalSection inserisce i due elementi condizionali per la selezione dell'elemento booleano in un oggetto separatoTableSection
. Il file code-behind rimuove questa sezione dall'oggetto TableView
o lo aggiunge nuovamente in base alla proprietà booleana.
Menu TableView
Un altro uso di è TableView
un menu. L'esempio MenuCommands illustra un menu che consente di spostare un po' BoxView
sullo schermo.