Zusammenfassung von Kapitel 19. Auflistungsansichten
Hinweis
Dieses Buch wurde im Frühjahr 2016 veröffentlicht und seitdem nicht aktualisiert. Wenngleich ein großer Teil des Buchs weiterhin relevante Informationen liefert, sind einige Abschnitte veraltet, und einige Themen sind nicht mehr korrekt oder vollständig.
In Xamarin.Forms sind drei Ansichten definiert, mit denen Auflistungen verwaltet und die zugehörigen Elemente angezeigt werden:
Picker
ist eine relativ kurze Liste mit Zeichenfolgenelementen, aus denen der Benutzer ein Element auswählen kannListView
ist häufig eine lange Liste mit Elementen, die normalerweise denselben Typ und dieselbe Formatierung aufweisen. Aus dieser Liste können Benutzer ebenfalls ein Element auswählenTableView
ist eine Auflistung von Zellen (in der Regel verschiedene Typen und Erscheinungen), mit denen Daten angezeigt und Benutzereingaben verwaltet werden können
MVVM-Anwendungen verwenden häufig ListView
, um eine auswählbare Auflistung von Objekten anzuzeigen.
Programmoptionen bei Picker
Picker
ist gut geeignet, wenn Sie es Benutzern ermöglichen möchten, eine Option aus einer relativ kurzen Liste von string
-Elementen auszuwählen.
Die Picker-Ansicht und die Ereignisbehandlung
Das Beispiel PickerDemo zeigt, wie Sie mithilfe von XAML die Picker
-Eigenschaft Title
festlegen und string
-Elemente zur Items
-Auflistung hinzufügen. Wenn der Benutzer Picker
auswählt, werden die Elemente in der Items
-Auflistung plattformabhängig angezeigt.
Das SelectedIndexChanged
-Ereignis zeigt an, wenn der Benutzer ein Element ausgewählt hat. Der nullbasierte SelectedIndex
-Eigenschaft zeigt dann das ausgewählte Element an. Wenn kein Element ausgewählt ist, SelectedIndex
entspricht "-1".
Sie können auch die Eigenschaft SelectedIndex
verwenden, um das ausgewählte Element zu initialisieren. Diese Eigenschaft muss jedoch nach dem Füllen der Items
-Auflistung festgelegt werden. In XAML bedeutet dies, dass Sie SelectedIndex
wahrscheinlich mit einem Eigenschaftselement festlegen.
Datenbindung und Picker
Die SelectedIndex
-Eigenschaft wird durch eine bindbare Eigenschaft gestützt, Items
jedoch nicht. Daher ist die Verwendung der Datenbindung mit Picker
schwierig. Eine Lösung besteht darin, Picker
in Kombination mit einem ObjectToIndexConverter
zu verwenden, z. B. mit dem in der Bibliothek Xamarin.FormsBook.Toolkit enthaltenen Konverter. Das Beispiel PickerBinding zeigt die Funktionsweise.
Hinweis
Das Xamarin.FormsPicker
jetzt enthält ItemsSource
und SelectedItem
Eigenschaften, die die Datenbindung unterstützen. Siehe Picker.
Rendern von Daten mit ListView
ListView
ist die einzige Klasse, die von der Klasse ItemsView<TVisual>
abgeleitet wird, von der sie die Eigenschaften ItemsSource
und ItemTemplate
erbt.
ItemsSource
weist den Typ IEnumerable
, standardmäßig jedoch den Wert null
auf und muss explizit initialisiert werden bzw. (die häufigere Vorgehensweise) mithilfe einer Datenbindung auf eine Auflistung festgelegt werden. Die Elemente in dieser Auflistung können einen beliebigen Typ aufweisen.
ListView
definiert eine SelectedItem
-Eigenschaft, die entweder auf eins der Elemente in der ItemsSource
-Auflistung oder auf null
festgelegt ist, wenn kein Element ausgewählt wird. Wenn ein neues Element ausgewählt wird, löst ListView
das Ereignis ItemSelected
aus.
Auflistungen und Auswahlmöglichkeiten
Im Beispiel ListViewList wird eine ListView
mit 17 Color
-Werten in einer List<Color>
-Auflistung gefüllt. Die Elemente können ausgewählt werden, werden standardmäßig jedoch in ihren weniger schönen ToString
-Darstellungen angezeigt. In verschiedenen Beispielen innerhalb dieses Kapitels wird gezeigt, wie sich diese Darstellung ändern lässt, um die Elemente in der gewünschten Form anzuzeigen.
Das Zeilentrennzeichen
Bei iOS und Android werden die Zeilen durch eine dünne Linie getrennt. Sie können dieses Verhalten über die Eigenschaften SeparatorVisibility
und SeparatorColor
steuern. Die Eigenschaft SeparatorVisibility
weist den Typ SeparatorVisibility
auf, eine Enumeration, die über zwei Member verfügt:
Datenbindung für das ausgewählte Element
Die Eigenschaft SelectedItem
wird durch eine bindbare Eigenschaft gestützt und kann folglich die Quelle oder das Ziel einer Datenbindung sein. Für BindingMode
ist standardmäßig OneWayToSource
festgelegt, im Allgemeinen ist die Eigenschaft jedoch das Ziel einer bidirektionalen Datenbindung (insbesondere in einem MVVM-Szenario). Diese Art von Bindung wird im Beispiel ListViewArray veranschaulicht.
Die Klasse „ObservableCollection“
Im Beispiel ListViewLogger wird die Eigenschaft ItemsSource
einer ListView
auf eine List<DateTime>
-Auflistung festgelegt. Anschließend wird fortwährend mithilfe eines Timers jede Sekunde ein neues DateTime
-Objekt hinzugefügt.
ListView
aktualisiert sich jedoch nicht automatisch selbst, da die List<T>
-Auflistung über keinen Benachrichtigungsmechanismus verfügt, der anzeigt, wenn Elemente zur Auflistung hinzugefügt oder aus der Auflistung entfernt werden.
In einem solchen Szenario sollte stattdessen die Klasse ObservableCollection<T>
verwendet werden, die im System.Collections.ObjectModel
-Namespace definiert ist. Diese Klasse implementiert die INotifyCollectionChanged
-Schnittstelle und löst daher ein CollectionChanged
-Ereignis aus, wenn Elemente zur Auflistung hinzugefügt oder aus der Auflistung entfernt werden. Auch wenn Elemente ersetzt oder innerhalb der Auflistung verschoben werden, wird ein Ereignis ausgelöst. Wenn ListView
intern erkennt, dass eine Klasse, die INotifyCollectionChanged
implementiert, auf ihre Eigenschaft ItemsSource
festgelegt wurde, fügt ListView einen Handler zum CollectionChanged
-Ereignis hinzu und aktualisiert die Anzeige, sobald die Auflistung sich ändert.
Die Verwendung von ObservableCollection
wird im Beispiel ObservableLogger veranschaulicht.
Vorlagen und Zellen
Eine ListView
-Klasse zeigt die Elemente in ihrer Auflistung standardmäßig mithilfe der ToString
-Methode der einzelnen Elemente an. Ein besserer Ansatz ist die Definition einer Vorlage, um die Elemente anzuzeigen.
Um diese Funktion auszuprobieren, können Sie die Klasse NamedColor
in der Bibliothek Xamarin.FormsBook.Toolkit verwenden. Diese Klasse definiert eine statische All
-Eigenschaft vom Typ IList<NamedColor>
mit 141 NamedColor
-Objekten, die den öffentlichen Feldern der Color
-Struktur entsprechen.
Im Beispiel NaiveNamedColorList wird ItemsSource
einer ListView
-Klasse auf diese NamedColor.All
-Eigenschaft festgelegt. Es werden jedoch nur die vollqualifizierten Klassennamen der NamedColor
-Objekte angezeigt.
ListView
benötigt eine Vorlage, um diese Elemente anzuzeigen. Im Code können Sie die von ItemsView<TVisual>
definierte Eigenschaft ItemTemplate
auf ein DataTemplate
-Objekt festlegen. Verwenden Sie dazu den DataTemplate
-Konstruktor, der auf eine Ableitung der Cell
-Klasse verweist. Cell
verfügt über fünf Ableitungen:
TextCell
— enthält zweiLabel
Ansichten (konzeptionell gesehen)ImageCell
— fügt eineImage
Ansicht hinzuTextCell
EntryCell
— enthält eineEntry
Ansicht mit einerLabel
SwitchCell
— enthält eineSwitch
mit einerLabel
ViewCell
— kann beliebigView
sein (wahrscheinlich mit Kindern)
Rufen Sie dann SetValue
und SetBinding
für das DataTemplate
-Objekt auf, um den Cell
-Eigenschaften Werte zuzuordnen oder um Datenbindungen für die Cell
-Eigenschaften festzulegen, die auf andere Eigenschaften der Objekte in der ItemsSource
-Auflistung verweisen. Dies wird im Beispiel TextCellListCode veranschaulicht.
Wenn ListView
alle Elemente anzeigt, wird anhand der Vorlage eine kleine visuelle Struktur erstellt. Außerdem werden zwischen dem Element und den Eigenschaften der Elemente in dieser visuellen Struktur Datenbindungen erstellt. Um sich mit diesem Vorgang vertraut zu machen, können Sie Handler für die ItemAppearing
- und ItemDisappearing
-Ereignisse von ListView
installieren. Eine weitere Möglichkeit besteht darin, einen alternativen DataTemplate
-Konstruktor zu einzusetzen, der eine Funktion verwendet, die jedes Mal aufgerufen wird, wenn die visuelle Struktur eines Elements erstellt werden muss.
Im Beispiel TextCellListXaml wird ein funktional identisches Programm in XAML gezeigt. Ein DataTemplate
-Tag wird auf die ItemTemplate
-Eigenschaft von ListView
festgelegt, anschließend wird TextCell
auf DataTemplate
festgelegt. Bindungen mit Eigenschaften der Elemente in der Auflistung werden direkt für die Text
- und Detail
-Eigenschaften von TextCell
festgelegt.
Benutzerdefinierte Zellen
In XAML ist es möglich, ViewCell
auf DataTemplate
festzulegen und dann eine benutzerdefinierte visuelle Struktur als View
-Eigenschaft von ViewCell
zu definieren. (View
ist die Inhaltseigenschaft, ViewCell
sodass die ViewCell.View
Tags nicht erforderlich sind.) Das CustomNamedColorList-Beispiel veranschaulicht diese Technik:
Das Ermitteln der richtigen Größe für alle Plattformen kann schwierig sein. Die RowHeight
-Eigenschaft ist nützlich, in einigen Fällen sollten Sie jedoch auf die HasUnevenRows
-Eigenschaft zurückgreifen. Diese Eigenschaft ist weniger effizient, erzwingt jedoch das Anpassen der Zeilengröße durch ListView
. Bei iOS und Android müssen Sie eine dieser beiden Eigenschaften verwenden, um die richtige Zeilengröße zu erhalten.
Gruppieren der ListView-Elemente
ListView
unterstützt das Gruppieren von Elementen sowie das Navigieren zwischen diesen Gruppen. Die ItemsSource
Eigenschaft muss auf eine Auflistung von Auflistungen festgelegt werden: Das objekt, auf das ItemsSource
festgelegt wird, muss implementiert IEnumerable
werden, und jedes Element in der Auflistung muss ebenfalls implementiert werden IEnumerable
. Jede Gruppe sollte zwei Eigenschaften enthalten: eine Textbeschreibung der Gruppe und eine aus drei Buchstaben bestehende Abkürzung.
Mit der Klasse NamedColorGroup
in der Bibliothek Xamarin.FormsBook.Toolkit werden sieben Gruppen mit NamedColor
-Objekten erstellt. Das Beispiel ColorGroupList zeigt, wie diese Gruppen verwendet werden. Dabei ist die IsGroupingEnabled
-Eigenschaft von ListView
auf true
festgelegt, und die Eigenschaften GroupDisplayBinding
und GroupShortNameBinding
sind an Eigenschaften in den einzelnen Gruppen gebunden.
Benutzerdefinierte Gruppenheader
Sie können benutzerdefinierte Header für die ListView
-Gruppen erstellen, indem Sie die GroupDisplayBinding
-Eigenschaft durch GroupHeaderTemplate
ersetzen. Auf diese Weise wird eine Vorlage für die Header definiert.
ListView und Interaktivität
Für die Benutzerinteraktion mit ListView
wird üblicherweise ein Handler an das ItemSelected
- oder ItemTapped
-Ereignis angefügt oder eine Datenbindung für die SelectedItem
-Eigenschaft festlegt. Es gibt jedoch auch Zellentypen (EntryCell
und SwitchCell
), die eine Benutzerinteraktion ermöglichen. Darüber hinaus ist es möglich, benutzerdefinierte Zellen zu erstellen, die selbst mit dem Benutzer interagieren. Mit InteractiveListView werden 100 Instanzen von ColorViewModel
erstellt. Außerdem kann der Benutzer mithilfe von drei Slider
-Elementen die einzelnen Farben ändern. Das Programm nutzt zudem den ColorToContrastColorConverter
in Xamarin.FormsBook.Toolkit.
ListView und MVVM
ListView
spielt in MVVM-Szenarien eine große Rolle. Wenn in einem ViewModel eine IEnumerable
-Auflistung vorhanden ist, ist sie oft an ein ListView
gebunden. Außerdem implementieren die Elemente in der Auflistung häufig INotifyPropertyChanged
, um eine Bindung mit Eigenschaften in einer Vorlage herzustellen.
Eine ViewModels-Auflistung
Um diese Funktion zu veranschaulichen, erstellt die SchoolOfFineArts-Bibliothek mehrere Klassen basierend auf einer XML-Datendatei sowie Bilder von fiktiven Studenten an dieser fiktiven Schule.
Die Student
-Klasse wird von ViewModelBase
abgeleitet. Die Klasse StudentBody
ist eine Auflistung aus Student
-Objekten und wird ebenfalls von ViewModelBase
abgeleitet. SchoolViewModel
lädt die XML-Datei herunter und setzt alle Objekte zusammen.
Das StudentList-Programm verwendet eine ImageCell
, um die Studenten und ihre Bilder in einer ListView
anzuzeigen:
Im Beispiel ListViewHeader wird eine Header
-Eigenschaft hinzugefügt, die jedoch nur unter Android angezeigt wird.
Auswahl und der Bindungskontext
Das Programm SelectedStudentDetail bindet den BindingContext
eines StackLayout
an die SelectedItem
-Eigenschaft von ListView
. Dadurch kann das Programm detaillierte Informationen zum ausgewählten Studenten anzeigen.
Kontextmenüs
In einer Zelle kann ein Kontextmenü definiert werden, das plattformspezifisch implementiert wird. Um dieses Menü zu erstellen, fügen Sie MenuItem
-Objekte zur ContextActions
-Eigenschaft der Cell
hinzu.
MenuItem
definiert fünf Eigenschaften:
Text
vom Typstring
Icon
vom TypFileImageSource
IsDestructive
vom Typbool
Command
vom TypICommand
CommandParameter
vom Typobject
Die Eigenschaften Command
und CommandParameter
implizieren, dass das ViewModel-Objekt für jedes Element Methoden zum Ausführen der gewünschten Menübefehle enthält. In Nicht-MVVM-Szenarien definiert MenuItem
zudem ein Clicked
-Ereignis.
Dieses Verfahren wird in CellContextMenu veranschaulicht. Die Command
-Eigenschaft jedes MenuItem
ist an eine Eigenschaft vom Typ ICommand
in der Student
-Klasse gebunden. Legen Sie die IsDestructive
-Eigenschaft für ein MenuItem
auf true
fest, wenn das Menüelement das ausgewählte Objekt entfernt oder löscht.
Variierende visuelle Elemente
In einigen Fällen sollen die Elemente der ListView
basierend auf einer Eigenschaft mit geringfügigen Variationen angezeigt werden. Im Beispiel ColorCodedStudents wird der Name eines Studenten z.B. rot angezeigt, wenn sein Notendurchschnitt unter 2.0 fällt.
Zu diesem Zweck wird der Bindungsdatenkonverter ThresholdToObjectConverter
aus der Bibliothek Xamarin.FormsBook.Toolkit verwendet.
Aktualisieren des Inhalts
ListView
unterstützt das Herunterziehen der Inhalte, um die Daten zu aktualisieren. Um diese Funktion zu aktivieren, muss das Programm die IsPullToRefresh
-Eigenschaft auf true
festlegen. ListView
reagiert auf das Herunterziehen, indem ihre IsRefreshing
-Eigenschaft auf true
festgelegt wird. Außerdem wird das Refreshing
-Ereignis ausgelöst und (für MVVM-Szenarien) die Execute
-Methode ihrer RefreshCommand
-Eigenschaft aufgerufen.
Code, der das Refresh
-Ereignis oder den RefreshCommand
verarbeitet, aktualisiert dann möglicherweise die Daten, die von ListView
angezeigt werden, und legt IsRefreshing
wieder auf false
fest.
Das Beispiel RssFeed veranschaulicht die Verwendung eines RssFeedViewModel
, das die Eigenschaften RefreshCommand
und IsRefreshing
für Datenbindungen implementiert.
TableView und die zugehörigen Intents
Während ListView
in der Regel mehrere Instanzen desselben Typs anzeigt, stellt TableView
im Allgemeinen eine Benutzeroberfläche für mehrere Eigenschaften unterschiedlicher Typen bereit. Jedes Element ist einer eigenen Cell
-Ableitung zum Anzeigen der Eigenschaft oder Bereitstellen einer Benutzeroberfläche zugeordnet.
Eigenschaften und Hierarchien
TableView
definiert nur vier Eigenschaften:
Intent
vom TypTableIntent
, eine EnumerationRoot
vom TypTableRoot
, die Inhaltseigenschaft (Content) vonTableView
.RowHeight
vom Typint
HasUnevenRows
vom Typbool
Die TableIntent
-Enumeration gibt an, wie Sie TableView
verwenden möchten:
Diese Member empfehlen außerdem einige Verwendungsmöglichkeiten für TableView
.
Für die Definition einer Tabelle werden eine Reihe weiterer Klassen verwendet:
TableSectionBase
ist eine abstrakte Klasse, die vonBindableObject
abgeleitet wird und eineTitle
-Eigenschaft definiertTableSectionBase<T>
ist eine abstrakte Klasse, die vonTableSectionBase
abgeleitet wird undIList<T>
undINotifyCollectionChanged
implementiertTableSection
wird vonTableSectionBase<Cell>
abgeleitetTableRoot
wird vonTableSectionBase<TableSection>
abgeleitet
Kurz gesagt verfügt TableView
über eine Root
-Eigenschaft, die Sie auf ein TableRoot
-Objekt festlegen, bei dem es sich um eine Auflistung von TableSection
-Objekten handelt. Jedes dieser Objekte ist wiederum ebenfalls eine Auflistung von Cell
-Objekten. Eine Tabelle verfügt über mehrere Abschnitte, und jeder Abschnitt enthält mehrere Zellen. Die Tabelle selbst und jeder Abschnitt kann über einen Titel verfügen. Wenngleich TableView
mit Cell
-Ableitungen arbeitet, wird DataTemplate
nicht verwendet.
Ein einfaches Formular
Das EntryForm-Beispiel definiert ein PersonalInformation
-Ansichtsmodell. Eine Instanz dieses Modells wird zum BindingContext
von TableView
. Jede Cell
-Ableitung in der zugehörigen TableSection
kann anschließend über Bindungen mit Eigenschaften der PersonalInformation
-Klasse verfügen.
Benutzerdefinierte Zellen
Im Beispiel ConditionalCells wird EntryForm erweitert. Die ProgrammerInformation
-Klasse enthält eine boolesche Eigenschaft, die die Anwendbarkeit von zwei zusätzlichen Eigenschaften regelt. Für diese beiden zusätzlichen Eigenschaften verwendet das Programm eine benutzerdefinierte PickerCell
, die auf PickerCell.xaml und PickerCell.xaml.cs in der Bibliothek Xamarin.FormsBook.Toolkit basiert.
Obwohl die IsEnabled
-Eigenschaften der beiden PickerCell
-Elemente an die boolesche Eigenschaft in ProgrammerInformation
gebunden sind, scheint dieses Verfahren nicht zu funktionieren. Aus diesem Grund wird das nächste Beispiel veranschaulicht.
Bedingungsabschnitte
Im Beispiel ConditionalSection werden die beiden bedingten Elemente der Auswahl des booleschen Elements in einer separaten TableSection
platziert. Die CodeBehind-Datei entfernt diesen Abschnitt aus der TableView
oder fügt ihn basierend auf der booleschen Eigenschaft erneut hinzu.
Ein TableView-Menü
Eine weitere Verwendungsmöglichkeit von TableView
ist ein Menü. Im Beispiel MenuCommands wird ein Menü gezeigt, in dem Sie eine kleine BoxView
auf dem Bildschirm verschieben können.