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 uno
  • ListView è spesso un lungo elenco di elementi di solito dello stesso tipo e formattazione, consentendo anche all'utente di sceglierne uno
  • TableView è 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 PickerTitle proprietà e aggiungere string elementi alla Items raccolta. Quando l'utente seleziona , Pickervisualizza 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 due Label visualizzazioni (concettualmente parlando)
  • ImageCell — aggiunge una Image visualizzazione a TextCell
  • EntryCell — contiene una Entry visualizzazione con un Label
  • SwitchCell — contiene un oggetto con un Switch oggetto Label
  • ViewCell — può essere qualsiasi View (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 ListViewoppure 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 ListViewe 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:

Screenshot triplo dell'elenco personalizzato dei colori denominati

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 IEnumerablee ogni elemento dell'insieme deve implementare IEnumerableanche . 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 truee 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 ListViewoggetto :

Screenshot triplo dell'elenco degli studenti

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

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 truee 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à:

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 da BindableObject e definisce una Title proprietà

  • TableSectionBase<T> è una classe astratta che deriva da TableSectionBase e implementa IList<T> e INotifyCollectionChanged

  • TableSection deriva da TableSectionBase<Cell>

  • TableRoot deriva da TableSectionBase<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 TableViewBindingContext . 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.