第 19 章的摘要。 清單和格線
注意
這本書於2016年春季出版,此後一直沒有更新。 這本書中有很多仍然有價值,但一些材料已經過時,有些主題不再完全正確或完整。
Xamarin.Forms 定義三個檢視來維護集合並顯示其元素:
Picker
是一個相對簡短的字串專案清單,可讓用戶選擇一個ListView
通常是一長串相同類型和格式的專案清單,也允許用戶選擇一個TableView
是用來顯示資料或管理使用者輸入的 儲存格 集合(通常是各種類型和外觀)
MVVM 應用程式通常會使用 ListView
來顯示可選取的物件集合。
使用選擇器的程序選項
Picker
當您需要允許使用者從相對簡短的專案清單中string
選擇選項時,是不錯的選擇。
選擇器和事件處理
PickerDemo 範例示範如何使用 XAML 來設定 屬性,Picker
Title
並將專案新增string
至Items
集合。 當用戶選取 Picker
時,它會以平臺相依的方式顯示集合中的 Items
專案。
事件 SelectedIndexChanged
指出使用者何時已選取專案。 以零起始 SelectedIndex
的屬性接著會指出選取的專案。 如果未選取任何專案, SelectedIndex
則等於 –1。
您也可以使用 SelectedIndex
來初始化選取的專案,但必須在集合填滿之後 Items
設定它。 在 XAML 中,這表示您可能會使用屬性項目來設定 SelectedIndex
。
數據系結選擇器
屬性 SelectedIndex
是由可系結屬性所支援,但 Items
不是,因此很難搭配 Picker
使用數據系結。 其中一個解決方案是搭配 Book.Toolkit 文件庫中的 ,搭配Xamarin.Forms使用 。Picker
ObjectToIndexConverter
PickerBinding 會示範其運作方式。
注意
現在 Xamarin.FormsPicker
包含 ItemsSource
支持數據系結的 和 SelectedItem
屬性。 請參閱 選擇器。
使用 ListView 轉譯數據
ListView
是衍生自ItemsView<TVisual>
其繼承 ItemsSource
和 ItemTemplate
屬性的唯一類別。
ItemsSource
型別為 IEnumerable
,但預設為 null
,且必須透過數據系結明確初始化或(更常見)設定為集合。 此集合中的專案可以是任何類型。
ListView
SelectedItem
定義屬性,該屬性會設定為集合中的ItemsSource
其中一個專案,如果未null
選取任何專案,則為 。 ListView
ItemSelected
選取新項目時引發 事件。
集合和選取專案
ListViewList 範例會在ListView
集合中填入 17 Color
個List<Color>
值。 專案是可選取的,但預設會以其不具吸引力 ToString
的表示來顯示。 本章中的數個範例示範如何修正該顯示,並視需要使其更具吸引力。
數據列分隔符
在iOS和Android上,細線會分隔數據列。 您可以使用和 SeparatorColor
屬性來控制此專案SeparatorVisibility
。 SeparatorVisibility
屬性的類型為 SeparatorVisibility
,列舉具有兩個成員:
數據系結選取的專案
屬性 SelectedItem
是由可系結屬性所支援,因此它可以是數據系結的來源或目標。 其預設值 BindingMode
為 OneWayToSource
,但通常是雙向數據系結的目標,特別是在MVVM案例中。 ListViewArray 範例示範這種類型的系結。
ObservableCollection 差異
ListViewLogger 範例會將 的 ListView
屬性設定ItemsSource
為List<DateTime>
集合,然後使用定時器每秒將新的 DateTime
物件加入至集合。
不過, ListView
不會自動更新本身,因為 List<T>
集合沒有通知機制可指出專案何時新增至集合或從集合中移除。
在命名空間中定義了更適合用於這類案例 ObservableCollection<T>
的 System.Collections.ObjectModel
類別。 這個類別會實作 INotifyCollectionChanged
介面,因此 CollectionChanged
會在專案新增至集合或從集合中移除專案時,或在集合內被取代或移動時引發事件。 ListView
當內部偵測到實作INotifyCollectionChanged
的類別已設定為其 ItemsSource
屬性時,它會將處理程式附加至 事件,CollectionChanged
並在集合變更時更新其顯示。
ObservableLogger 範例示範 如何使用 ObservableCollection
。
範本和儲存格
根據預設,會 ListView
使用每個專案的方法,顯示其集合中的專案 ToString
。 更好的方法包括定義範本來顯示專案。
若要試驗這項功能,您可以使用 NamedColor
Book.Toolkit 連結庫中的 Xamarin.Forms類別。 這個類別會定義 類型的靜態All
屬性,其中包含141 NamedColor
個對應至結構公用欄位的物件Color
。IList<NamedColor>
NaiveNamedColorList 範例會將 的 設定為這個NamedColor.All
屬性,但只會顯示物件的完整類別名稱NamedColor
。ItemsSource
ListView
ListView
需要範本才能顯示這些專案。 在程式代碼中,您可以使用參考 類別衍生的建構函式,將 所ItemsView<TVisual>
定義的 屬性設定ItemTemplate
為 DataTemplate
物件DataTemplate
。Cell
Cell
有五個衍生專案:
TextCell
— 包含兩Label
個檢視(概念上講)ImageCell
— 將檢視新增Image
至TextCell
EntryCell
— 包含Entry
具有的檢視Label
SwitchCell
— 包含Switch
具有的Label
ViewCell
— 可以是任何View
(可能與孩子在一起)
然後在 物件上呼叫 SetValue
和 SetBinding
,以將值與Cell
屬性產生關聯,或是在參考集合中ItemsSource
專案屬性的屬性上Cell
設定DataTemplate
數據系結。 這會在 TextCellListCode 範例中示範。
當每個專案都由 ListView
顯示時,會從範本建構小型可視化樹狀結構,而數據系結會在專案與這個可視化樹狀結構中的專案屬性之間建立。 您可以藉由安裝的與事件的處理程式,或使用使用每次建立項目可視化樹狀結構時呼叫之函式的替代DataTemplate
建構函式,來瞭解此程式。ListView
ItemDisappearing
ItemAppearing
TextCellListXaml 在 XAML 中顯示功能完全相同的程式。 標記 DataTemplate
會設定為 ItemTemplate
的 ListView
屬性,然後將 TextCell
設定為 DataTemplate
。 集合中專案之屬性的系結會直接在 的 和 Detail
屬性TextCell
上Text
設定。
自定義儲存格
在 XAML 中,可以將 設定 ViewCell
為 DataTemplate
,然後將自定義可視化樹狀 View
結構定義為 的 ViewCell
屬性。 (View
是 的內容屬性 ViewCell
, ViewCell.View
因此不需要標記。 CustomNamedColorList 範例示範這項技術:
為所有平台調整大小可能很棘手。 屬性 RowHeight
很有用,但在某些情況下,您會想要求助於 HasUnevenRows
屬性,其效率較低,但會強制 ListView
調整數據列的大小。 針對iOS和Android,您必須使用這兩個屬性的其中一個來取得適當的數據列重設大小。
將 ListView 專案分組
ListView
支持專案分組,並在這些群組之間巡覽。 屬性 ItemsSource
必須設定為集合集合:設定為 的物件 ItemsSource
必須實 IEnumerable
作 ,而且集合中的每個項目也必須實 IEnumerable
作 。 每個群組都應該包含兩個屬性:群組的文字描述和三個字母縮寫。
Book.Toolkit 連結庫中的Xamarin.Forms 類別會建立七組NamedColor
物件。NamedColorGroup
ColorGroupList 範例示範如何使用這些群組,並將 IsGroupingEnabled
屬性ListView
設定為 true
,以及GroupDisplayBinding
系結至每個群組中屬性的 和 GroupShortNameBinding
屬性。
自定義群組標頭
藉由將 屬性GroupHeaderTemplate
取代GroupDisplayBinding
為定義標頭的範本,即可為群組建立自定義標頭ListView
。
ListView 和互動性
一般而言,應用程式會藉由將處理程式附加至 ItemSelected
或 ItemTapped
事件,或在 屬性上SelectedItem
設定數據系結,來取得使用者與 ListView
的互動。 但某些儲存格型態 (EntryCell
和 SwitchCell
) 允許使用者互動,而且也可以建立自己與使用者互動的自定義儲存格。 InteractiveListView 會建立 100 個 實例ColorViewModel
,並允許使用者使用三個Slider
元素來變更每個色彩。 程式也會使用 ColorToContrastColorConverter
Book.Toolkit 中的 Xamarin.Forms。
ListView 和MVVM
ListView
在MVVM案例扮演重要角色。 每當 IEnumerable
ViewModel 中有集合時,通常會繫結至 ListView
。 此外,集合中的專案通常會實 INotifyPropertyChanged
作以系結至範本中的屬性。
ViewModels 的集合
為了探索這一點,SchoolOfFineArts 連結庫會根據這個虛構學校虛構學生的 XML 數據檔和影像建立數個課程。
Student
類別衍生自 ViewModelBase
。 類別 StudentBody
是 物件的集合 Student
,也衍生自 ViewModelBase
。 會 SchoolViewModel
下載 XML 檔案,並組合所有物件。
StudentList 計劃會使用 ImageCell
,在 中ListView
顯示學生及其影像:
ListViewHeader 範例會新增Header
屬性,但只會顯示在 Android 上。
選取專案和系結內容
SelectedStudentDetail 程式會將 BindingContext
的 StackLayout
系結至 SelectedItem
的 ListView
屬性。 這可讓程序顯示所選學生的詳細資訊。
操作功能表
單元格可以定義以平臺特定方式實作的操作功能表。 若要建立此功能表,請將 物件新增 MenuItem
至 ContextActions
的 Cell
屬性。
MenuItem
定義五個屬性:
- 型別
Text
的string
- 型別
Icon
的FileImageSource
- 型別
IsDestructive
的bool
- 型別
Command
的ICommand
- 型別
CommandParameter
的object
Command
和 CommandParameter
屬性表示每個專案的 ViewModel 包含執行所需功能表命令的方法。 在非MVVM案例中, MenuItem
也會定義 Clicked
事件。
CellContextMenu 示範這項技術。 Command
每個 MenuItem
屬性都會系結至 類別中Student
型別ICommand
的屬性。 將 IsDestructive
屬性 true
設定為 MenuItem
,以移除或刪除選取的物件。
改變視覺效果
有時候,您會想要根據 屬性,在 中 ListView
項目的視覺效果稍有變化。 例如,當學生的成績分數平均低於 2.0 時, ColorCodedStudents 範例會以紅色顯示學生的名稱。
這是透過在 Book.Toolkit 連結庫中使用系結值轉換器ThresholdToObjectConverter
Xamarin.Forms來完成的。
重新整理內容
ListView
支援下拉手勢來重新整理其數據。 程序必須將 屬性設定 IsPullToRefresh
為 true
,才能啟用此功能。 會 ListView
藉由將其 IsRefreshing
屬性設定為 true
來回應下拉手勢,並藉由引發 Refreshing
事件和 (針對MVVM案例)呼叫 Execute
其 RefreshCommand
屬性的方法。
處理 Refresh
事件的程式代碼,或 RefreshCommand
之後可能會更新 所 ListView
顯示的數據,並將 設定 IsRefreshing
回 false
。
RssFeed 範例示範如何使用 RssFeedViewModel
實作 RefreshCommand
數據系結的 和 IsRefreshing
屬性。
TableView 及其意圖
ListView
雖然 通常會顯示相同型別的多個實例,TableView
但 通常著重於為各種類型的多個屬性提供用戶介面。 每個項目都會與其本身 Cell
的衍生專案相關聯,以便顯示屬性或提供使用者介面給它。
屬性和階層
TableView
只定義四個屬性:
Intent
型TableIntent
別為 ,列舉Root
型TableRoot
別為 的 ,其內容屬性為TableView
- 型別
RowHeight
的int
- 型別
HasUnevenRows
的bool
TableIntent
列舉表示您打算TableView
如何使用 :
這些成員也建議使用 。TableView
定義資料表時涉及數個其他類別:
TableSectionBase
是衍生自BindableObject
併定義屬性的Title
抽象類TableSectionBase<T>
是衍生自TableSectionBase
和實作 和的IList<T>
抽象類INotifyCollectionChanged
TableSection
來自TableSectionBase<Cell>
TableRoot
來自TableSectionBase<TableSection>
簡言之, TableView
有一個屬性,您設定為 Root
TableRoot
物件,這是 物件的集合 TableSection
,每個物件都是 物件的集合 Cell
。 數據表有多個區段,而且每個區段都有多個單元格。 數據表本身可以有標題,而且每個區段都可以有標題。 雖然 TableView
會使用 Cell
衍生專案,但不會使用 DataTemplate
。
prosaic 表單
EntryForm 範例會PersonalInformation
定義檢視模型,其實例會BindingContext
成為的 TableView
。 然後,其Cell
TableSection
中的每個衍生專案都可以有 類別屬性的PersonalInformation
系結。
自定義儲存格
ConditionalCells 範例會展開 EntryForm。 類別 ProgrammerInformation
包含一個布爾屬性,可控管兩個額外屬性的適用性。 針對這兩個額外的屬性,程式會根據 Book.Toolkit 連結庫中的 PickerCell.xaml 和PickerCell.xaml.csXamarin.Forms使用自定義。PickerCell
IsEnabled
雖然這兩PickerCell
個元素的屬性系結至 中的ProgrammerInformation
布爾屬性,但這項技術似乎無法運作,這會提示下一個範例。
條件區段
ConditionalSection 範例會將條件式選取布爾專案的兩個專案放在不同的 TableSection
中。 程序代碼後置檔案會從 TableView
移除這個區段,或根據 Boolean 屬性將其新增回去。
TableView 功能表
另一種用法 TableView
是功能表。 MenuCommands 範例示範一個功能表,可讓您在畫面周圍移動一點BoxView
。