ListView用來顯示列表數(shù)據(jù)贮喧,適合單一類型數(shù)據(jù)集合铲球。
ListView屬性
- Footer :object類型野蝇,獲取名扛、設(shè)置列表底部的字符串或視圖谅年。
- FooterTemplate :DataTemplate類型,獲取肮韧、設(shè)置列表底部數(shù)據(jù)模版融蹂。
- Header :object類型,獲取弄企、設(shè)置列表頂部的字符串或視圖超燃。
- HeaderTemplate :DataTemplate類型,獲取拘领、設(shè)置列表定部數(shù)據(jù)模版意乓。
- HasUnevenRows :bool類型,表示列表是否有不均勻的行高院究,默認(rèn)值false洽瞬,設(shè)置為true后ListView每行的高度會因為內(nèi)容不同而提供不同高度。
可以在運行時通過Cell.ForceUpdateSize
方法更新cell大小业汰。
- IsGroupingEnabled :bool類型伙窃,表示是否對列表進行分組。
- GroupDisplayBinding:綁定分組頭的值样漆。
- GroupHeaderTemplate:DataTemplate類型为障,分組頭的數(shù)據(jù)模版。
- GroupShortNameBinding:綁定分組跳轉(zhuǎn)列表中的值放祟。
- IsPullToRefreshEnabled :bool類型鳍怨,表示列表是否可以進行下拉刷新。
- IsRefreshing :bool類型跪妥,表示列表是否正在刷新鞋喇。
- RowHeight :表示列表行高。
- SelectedItem :object類型眉撵,表示列表當(dāng)前選中對象侦香。
- SeparatorColor :表示列表分割欄的顏色落塑。
- SeparatorVisibility :SeparatorVisibility枚舉,表示分割欄的顯示方式罐韩。
ListView事件
- ItemAppearing :ListView元素顯示時觸發(fā)憾赁,ListView滑動使Item顯示在屏幕內(nèi)。
- ItemDisappearing :ListView元素消失時觸發(fā)散吵,ListView滑動使Item消失在屏幕內(nèi)龙考。
- ItemSelected :新的Item元素被選中時觸發(fā)。
- ItemTapped :ListView的元素Item被點擊是觸發(fā)矾睦。
- Refreshing :ListView刷新事件晦款。
ListView基本使用
填充ListView顯示的數(shù)據(jù)有兩種方式:設(shè)置ListView的ItemsSource和Data Binding。Data Binding后面介紹枚冗。ItemsSource類型是IEnumerable
柬赐。
XAML定義ListView會默認(rèn)填充整個屏幕
<ListView x:Name="listView"/>
通過C#代碼設(shè)置ItemsSource:
listView.ItemsSource = new List<string>() {
"List Item 1","List Item 2","List Item 3","List Item 4","List Item 5"
};
IOS會有多余分割線顯示可以通過代碼隱藏分割線listView.SeparatorVisibility = SeparatorVisibility.None;
默認(rèn)情況下ItemSource集合提供的數(shù)據(jù)調(diào)用ToString方法顯示在TextCell
上,即
ListView每行是一個TextCell
官紫。
定義XAML時設(shè)置ItemsSource:
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
<x:String>Item 4</x:String>
<x:String>Item 5</x:String>
<x:String>Item 6</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
ListView 結(jié)合 Data Binding使用
ListView的數(shù)據(jù)源(ItemsSource)不僅可以是簡單的字符串集合也可以是自定義的Model類集合肛宋,要顯示類集合數(shù)據(jù)時需要結(jié)合Data Binding實現(xiàn),演示一個TextCell顯示Text和Detail的示例束世。
Data Source設(shè)置代碼酝陈,ListViewItem是一個簡單的Model類不再展示:
在定義ItemSource的數(shù)據(jù)集合時推薦用ObservableCollection<T>代替List<T>,ObservableCollection實現(xiàn)了INotifyPropertyChanged接口能夠通知數(shù)據(jù)的變化,提供更新功能毁涉。
在XAML代碼中定義ListVIew時應(yīng)顯示指出TextCell的展現(xiàn)形式沉帮。設(shè)置ListView.ItemTemplate
,DataTemplate元素節(jié)點內(nèi)定義一個TextCell,綁定 TextCell的Text和Detail屬性為對應(yīng)Model的屬性贫堰。
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" Detail="{Binding Detail}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListView Selected事件
當(dāng)用戶點擊ListView的Item時觸發(fā)ListView的ItemTapped
事件穆壕,SelectedItem值發(fā)生改變還會觸發(fā)ItemSelected
事件,用戶連續(xù)點擊同一個Item時ItemTapped觸發(fā)多次其屏,SelectedItem只會在第一次點擊時觸發(fā)喇勋。
如果想使ListView禁用ListView被取消ListView的選中效果
listView.ItemSelected += (sender, e) => {
listView.SelectedItem = null;
};
ListView Cell介紹
前面有提到過TextCell,是Xamarin.Forms 提供的Cell子類可以幫助我們顯示更復(fù)雜的ListView偎行。
Xamarin.Forms提供給ListVIew常用的Cell有兩種:
TextCell
和ImageCell
川背。SwitchCell
和EntryCell
通常用在TableView中。
TextCell用來顯示文本蛤袒,并允許在第二行顯示詳細(xì)文本:
Text
– 顯示在第一行的文本熄云,以較大字體顯示.
Detail
– 以較小字體顯示在第二行的文本.
TextColor
– Text文本顏色.
DetailColor
– Detail文本顏色.
ImageCell與TextCell相比在Cell的左側(cè)可以顯示圖片信息。ImageCell顯示圖片在Windows Phone 8.1 下默認(rèn)不會縮放妙真,所以會有如下效果:
至于Windows Phone顯示效果沒有親自測試缴允,默認(rèn)不會縮放在官網(wǎng)中有提到,不開發(fā)Windows Phone可以不考慮珍德。
具體使用參考ListView 結(jié)合 Data Binding使用练般。更復(fù)雜的列表效果需自定義單元格健蕊,繼承ViewCell
實現(xiàn)期望的效果。自定義單元格更多信息參考:https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/customizing-cell-appearance/#Custom_Cells
ListView的Header和Footer
可以在ListView的頭部和尾部添加顯示簡單的文本或更加復(fù)雜的視圖布局踢俄。ListView的Header和Footer會隨ListView一起滾動。
如設(shè)置ListView的Header為一個簡單的字符串Footer為一個按鈕:
<ListView x:Name="listView">
<ListView.Header>
ListView Header
</ListView.Header>
<ListView.Footer>
<Button Text="Load More"/>
</ListView.Footer>
</ListView>
HeaderTemplate和FooterTemplate不是必須的晴及,涉及到數(shù)據(jù)綁定時才會用到都办。
如圖效果:
加載更多效果可以通過Footer設(shè)置為一個Button點擊加載跟多數(shù)據(jù)。
ListView分組
當(dāng)ListView展示大量數(shù)據(jù)時可以嘗試通過分組管理虑稼、展示數(shù)據(jù)琳钉,如iOS的通訊錄。
對ListView分組前蛛倦,必須先將數(shù)據(jù)進行分組歌懒,ListView分組的數(shù)據(jù)源應(yīng)該是集合的集合(collection of collections,后面給出示例)溯壶。準(zhǔn)備好數(shù)據(jù)源同時將ListView 的IsGroupingEnabled
屬性設(shè)置為true及皂,表示ListView開啟分組功能。ListView提供了GroupDisplayBinding
屬性且改,用來綁定每個分組的Title验烧,GroupShortNameBinding
綁定一個索引字段。所以定義的GroupModel應(yīng)該包含一個Title屬性綁定到GroupDisplayBinding屬性(必須的)又跛,定義一個ShortName綁定到GroupShortNameBinding(可選值)碍拆,iOS會在右側(cè)提供一個索引列表。
本文示例慨蓝,ListView的item展現(xiàn)的是簡單的字符串感混,所以GroupModel定義繼承IEnumerable<string>,并定義Title和ShortName屬性用來綁定ListView的GroupDisplayBinding和GroupShortNameBinding屬性。定義一個IEnumerable<ItemModel>屬性表示沒個分組的數(shù)據(jù)礼烈,本例中ListView展示字符串?dāng)?shù)據(jù)弧满,所以定義為IEnumerable<sttring>。定義如下Model類:
public class ListViewGroup : ObservableCollection<string>
{
public string GroupTitle
{
get;
set;
}
public string ShortName
{
get;
set;
}
public static ObservableCollection<ListViewGroup> Items
{
get;
set;
}
static ListViewGroup()
{
Items = new ObservableCollection<ListViewGroup>();
//創(chuàng)建虛擬數(shù)據(jù)
var aGroup = new ListViewGroup
{
GroupTitle = "A Title",
ShortName = "A"
};
aGroup.Add("Abs");
aGroup.Add("Apple");
aGroup.Add("Are");
aGroup.Add("Add");
Items.Add(aGroup);
var bGroup = new ListViewGroup
{
GroupTitle = "B Title",
ShortName = "B"
};
bGroup.Add("Bbs");
bGroup.Add("Blue");
bGroup.Add("Bar");
bGroup.Add("Bana");
Items.Add(bGroup);
var cGroup = new ListViewGroup
{
GroupTitle = "C Title",
ShortName = "C"
};
cGroup.Add("Cbs");
cGroup.Add("Couple");
cGroup.Add("Cut");
cGroup.Add("Custum");
Items.Add(cGroup);
var dGroup = new ListViewGroup
{
GroupTitle = "D Title",
ShortName = "D"
};
dGroup.Add("Dbs");
dGroup.Add("Double");
dGroup.Add("Delete");
dGroup.Add("Developer");
Items.Add(dGroup);
}
}
XAML中綁定數(shù)據(jù)此熬,通過x:Static指定數(shù)據(jù)源為ListViewGroup的靜態(tài)屬性Items谱秽,設(shè)置IsGroupingEnabled為true,綁定GroupTitle的值到GroupDisplayBinding摹迷,同時綁定GroupShortNameBinding的值(不是必須的)疟赊,ListView.RowHeight屬性節(jié)點定義不同平臺Item顯示不同高度。結(jié)合Custum Cell知識峡碉,定義ItemTemplate的值:
<ListView ItemsSource="{x:Static local:ListViewGroup.Items}"
IsGroupingEnabled="true"
GroupDisplayBinding="{Binding GroupTitle}"
GroupShortNameBinding="{Binding ShortName}">
<ListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32"
iOS="80"
Android="80"
WinPhone="90" />
</ListView.RowHeight>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="5">
<Frame OutlineColor="Accent"
Padding="10">
<StackLayout Orientation="Horizontal">
<BoxView Color="#00ffdd"
WidthRequest="50"
HeightRequest="50" />
<Label Text="{Binding .}"
FontSize="22"
VerticalOptions="StartAndExpand" />
</StackLayout>
</Frame>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Android近哟、iOS效果圖(GroupShortNameBinding屬性對Android平臺無效):
與定義ItemTemplate類似,ListView提供了GroupHeaderTemplate屬性方便我們自定義ListView的Group Header樣式鲫寄。示例代碼:
<ListView.GroupHeaderTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding ShortName}"
TextColor="#f35e20"
DetailColor="#503026" />
</DataTemplate>
</ListView.GroupHeaderTemplate>
ListView 刷新
設(shè)置ListView的IsPullToRefreshEnabled
屬性為true吉执,使ListView支持下拉刷新疯淫。
下拉ListView有如下效果:
用戶下拉ListView會觸發(fā)Refreshing事件,在處理Refreshing事件重新加載數(shù)據(jù)后應(yīng)通過設(shè)置IsRefreshing
為false或調(diào)用ListView的EndRefresh
方法通知ListView數(shù)據(jù)加載完成以取消下拉加載的效果戳玫。
也可以通過調(diào)用ListView 的
BeginRefresh
方法觸發(fā)Refreshing事件熙掺。
ListView Context Actions
有時我們需要為ListView的每一項提供菜單行為,如Item的刪除咕宿。IOS為左滑動Item币绩,Android和Windows Phone為長按Item。
Context Actions依靠MenuItem實現(xiàn)府阀,可以通過C#或XAML代碼定義缆镣。MenuItem提供了Clicked事件響應(yīng)MenuItem的點擊,MenuItem繼承BaseMenuItem试浙,有三個常用屬性屬性:
- Text – string類型董瞻,表示MenuItem顯示文本.
- Icon – FileImageSource類型,表示MenuItem圖標(biāo).
- IsDestructive – bool類型,值為true時iOS平臺MenuItem以紅色背景渲染.
C# 定義Context Action
定義MenuItem添加到Cell的ContextActions屬性中即可。這里不再給出C#代碼設(shè)置ListView的ItemTemplate示例田巴,所以圖片代碼為代碼片段钠糊。可參考:http://stackoverflow.com/questions/38585153/implementing-xamarin-forms-context-actions
默認(rèn)情況下響應(yīng)MenuItem的點擊事件并不能判斷當(dāng)前MenuItem屬于哪個Cell壹哺,可以通過MenuItem的CommandParameter屬性綁定一個值確定操作的Cell眠蚂。參考MenuItem響應(yīng)事件。
XAML 定義Context Action:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" Detail="{Binding Detail}">
<TextCell.ContextActions>
<MenuItem Clicked="OnShare" CommandParameter="{Binding .}" Text="分享" />
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}" Text="刪除" IsDestructive="True" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListView 性能優(yōu)化
應(yīng)用程序中使用ListView一定要確保ListView的性能(快速加載和平滑滾動)斗躏。Xamarin.Forms提供了Caching Strategy(緩存策略)優(yōu)化ListView使用性能,對應(yīng)ListView的CachingStrategy
屬性逝慧。也可以通過ListView使用過程中的一些技巧提升ListView的性能。
Caching Strategy
ListView用來展示大量數(shù)據(jù)啄糙,默認(rèn)情況下ListView會為每條記錄創(chuàng)建一個Cell笛臣,耗費大量內(nèi)存,通過Caching Strategy減少內(nèi)存使用隧饼,提高ListView性能沈堡。ListViewCachingStrategy枚舉包含兩個值RetainElement和RecycleElement。
RetainElement:
為列表中的沒一項生成一個Cell燕雁,是ListView的默認(rèn)行為诞丽。如下情況應(yīng)使用該值:
- 每個單元格(Cell)擁有大量的數(shù)據(jù)綁定(20-30+).
- 單元格模版(Cell Template)變化頻繁。
- 設(shè)置為RecycleElement值時ListView性能降低拐格,應(yīng)使用該值僧免。(When testing reveals that the RecycleElement value results in a reduced execution speed. )
RecycleElement:
設(shè)置為該值時ListView嘗試通過重復(fù)利用Cell減少內(nèi)存使用和提高執(zhí)行速度。RecycleElement不一定會提高ListView的使用性能捏浊,但如下情況應(yīng)使用該值:
- 單元格有很少的數(shù)據(jù)綁定
- 沒個單元格的數(shù)據(jù)源由Cell的BindingContext屬性提供
- 沒個單元格擁有相同的單元格模版
XAML中通過代碼CachingStrategy="RecycleElement"
指定CachingStrategy的模式懂衩。C#代碼中ListView沒有提供CachingStrategy屬性,設(shè)置CachingStrategy的值要在ListView 的構(gòu)造函數(shù)中傳入設(shè)置的值。
ListView設(shè)置CachingStrategy="RecycleElement"浊洞,簡單的顯示string集合出現(xiàn)元素顯示重復(fù)問題牵敷。
顯式設(shè)置ListView.ItemTemplate后運行正常。
<ListView x:Name="listView" CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding .}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
自定義Cell時應(yīng)該重寫OnBindingContextChanged方法法希,以保證設(shè)置ListView的屬性CachingStrategy="RecycleElement"時顯示正常枷餐。
Improving ListView Performance
ListView使用過程中很多技巧可以幫助我們提高ListView的性能:
- 對于綁定的數(shù)據(jù)源用IList<T> 集合代替 IEnumerable<T>集合。
- 盡量使用Forms提供的Cell(TextCell / SwitchCell)苫亦,避免自定義Cell毛肋。
- 自定Cell時減少布局嵌套和使用視圖,布局盡量使用AbsoluteLayout 和 Grid著觉,對于LayoutOptions屬性盡量設(shè)置為Fill。
- 顯示不規(guī)律數(shù)據(jù)時用TableView代替ListView惊暴。
- 減少Cell.ForceUpdateSize方法的調(diào)用饼丘。
- 避免將ListView放置在ScrollView中使用。
- 過于復(fù)雜的Cell辽话,盡量使用Custom Renderer(以后介紹)肄鸽。