Cell外觀
探索用於呈現數據的選項,同時利用ListView的便利。
ListView提供可滾動列表,可以通過使用ViewCell
s 進行自定義。ViewCells
可用於顯示文本和圖像,指示真/假狀態並接收用戶輸入。
從ListView單元格中可以看到兩種方法:
內置單元格
Xamarin.Forms配有內置單元格,適用於許多簡單的應用程序:
- TextCell - 用於顯示文本
- ImageCell - 用於顯示帶有文本的圖像。
另外兩個細胞,SwitchCell
並EntryCell
可用,但它們不是通常與使用ListView
。查看TableView
有關這些單元格的更多信息。
TextCell
TextCell
是用於顯示文本的單元格,可選地具有第二行作爲詳細文本。
TextCells在運行時呈現爲本機控件,因此與自定義相比,性能非常好ViewCell
。TextCells是可定製的,允許您設置:
Text
- 第一行顯示的文字,大字體。Detail
- 第一行顯示的文本,字體較小。TextColor
- 文字的顏色。DetailColor
- 細節文字的顏色
的ImageCell
ImageCell
,TextCell
可以用於顯示文本和二次詳細文本,並通過使用每個平臺的本機控件提供了很好的性能。ImageCell
不同之處TextCell
在於它顯示文本左側的圖像。
ImageCell
當您需要顯示具有可視化方面的數據列表(例如聯繫人或電影列表)時,此功能非常有用。ImageCells是可定製的,允許您設置:
Text
- 第一行顯示的文字,大字體Detail
- 第一行顯示的文本,字體較小TextColor
- 文字的顏色DetailColor
- 細節文字的顏色ImageSource
- 文本旁邊顯示的圖像
請注意,當定位到Windows Phone 8.1時,ImageCell
默認情況下不會縮放圖像。另外請注意,默認情況下,Windows Phone 8.1是唯一以與主文本相同的顏色和字體顯示細節文本的平臺。Windows Phone 8.0呈現ImageCell
如下:
自定義單元格
當內置單元格不提供所需的佈局時,自定義單元格實現了所需的佈局。例如,您可能想要呈現一個具有相同權重的兩個標籤的單元格。A LabelCell
將不夠,因爲它LabelCell
有一個較小的標籤。
所有自定義單元格必須從ViewCell
所有內置單元格類型使用的相同基類派生。
大多數單元格自定義添加額外的只讀數據(如附加標籤,圖像或其他顯示信息)。如果添加了可以聚焦的按鈕或其他控件,則在Android上可能無法點擊單元本身。見下文,以克服這個限制。
Xamarin.Forms 2 在控件上引入了一個新的緩存行爲ListView
,可以將其設置爲提高某些類型的自定義單元格的滾動性能。
這是一個自定義單元格的示例:
XAML
XAML創建上述佈局如下:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="demoListView.ImageCellPage">
<ContentPage.Content>
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="{Binding image}" />
<Label Text="{Binding title}"
TextColor="#f35e20" />
<Label Text="{Binding subtitle}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
上面的XAML正在做很多。我們來吧吧
- 自定義單元格嵌套在一個
DataTemplate
內部ListView.ItemTemplate
。這是與使用任何其他單元格相同的過程。 ViewCell
是自定義單元格的類型。DataTemplate
元素的子元素必須是或從類型導出的ViewCell
。- 注意在裏面
ViewCell
,佈局是由a管理的StackLayout
。此佈局允許我們自定義背景顏色。請注意,任何StackLayout
可綁定的屬性可以綁定到自定義單元格內,儘管此處未顯示。
C#
在C#中指定一個自定義單元格比XAML等效的更加冗長。讓我們來看看:
首先,定義一個自定義單元格類ViewCell
作爲基類:
public class CustomCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image ();
StackLayout cellWrapper = new StackLayout ();
StackLayout horizontalLayout = new StackLayout ();
Label left = new Label ();
Label right = new Label ();
//set bindings
left.SetBinding (Label.TextProperty, "title");
right.SetBinding (Label.TextProperty, "subtitle");
image.SetBinding (Image.SourceProperty, "image");
//Set properties for desired design
cellWrapper.BackgroundColor = Color.FromHex ("#eee");
horizontalLayout.Orientation = StackOrientation.Horizontal;
right.HorizontalOptions = LayoutOptions.EndAndExpand;
left.TextColor = Color.FromHex ("#f35e20");
right.TextColor = Color.FromHex ("503026");
//add views to the view hierarchy
horizontalLayout.Children.Add (image);
horizontalLayout.Children.Add (left);
horizontalLayout.Children.Add (right);
cellWrapper.Children.Add (horizontalLayout);
View = cellWrapper;
}
}
在您的頁面的構造函數中ListView
,將ListView的ItemTemplate
屬性設置爲新的DataTemplate
:
public partial class ImageCellPage : ContentPage
{
public ImageCellPage ()
{
InitializeComponent ();
listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
}
}
請注意,構造函數DataTemplate
需要一個類型。typeof運算符獲取CLR類型CustomCell
。
綁定上下文更改
當綁定到自定義單元格類型的BindableProperty
實例時,顯示BindableProperty
值的UI控件應該使用OnBindingContextChanged
override來設置要在每個單元格中顯示的數據,而不是單元格構造函數,如下面的代碼示例所示:
public class CustomCell : ViewCell
{
Label nameLabel, ageLabel, locationLabel;
public static readonly BindableProperty NameProperty =
BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
public static readonly BindableProperty AgeProperty =
BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
public static readonly BindableProperty LocationProperty =
BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");
public string Name {
get { return(string)GetValue (NameProperty); }
set { SetValue (NameProperty, value); }
}
public int Age {
get { return(int)GetValue (AgeProperty); }
set { SetValue (AgeProperty, value); }
}
public string Location {
get { return(string)GetValue (LocationProperty); }
set { SetValue (LocationProperty, value); }
}
...
protected override void OnBindingContextChanged ()
{
base.OnBindingContextChanged ();
if (BindingContext != null) {
nameLabel.Text = Name;
ageLabel.Text = Age.ToString ();
locationLabel.Text = Location;
}
}
}
該OnBindingContextChanged
倍率將被稱爲當BindingContextChanged
事件觸發,響應的價值BindingContext
特性改變。因此,當BindingContext
更改時,顯示BindableProperty
值的UI控件應設置其數據。請注意,BindingContext
應該檢查一個null
值,因爲這可以由Xamarin.Forms設置爲垃圾回收,這反過來將導致OnBindingContextChanged
覆蓋被調用。
或者,UI控件可以綁定到BindableProperty
實例以顯示其值,從而無需覆蓋該OnBindingContextChanged
方法。
當覆蓋時OnBindingContextChanged
,請確保OnBindingContextChanged
調用基類的方法,以便註冊的代理接收BindingContextChanged
事件。
在XAML中,可以將自定義單元格類型綁定到數據,如下面的代碼示例所示:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
此結合Name
,Age
和Location
可綁定屬性在CustomCell
比如,對Name
,Age
和Location
底層集合中的每個對象的屬性。
C#中的等效綁定如下代碼示例所示:
var customCell = new DataTemplate (typeof(CustomCell));
customCell.SetBinding (CustomCell.NameProperty, "Name");
customCell.SetBinding (CustomCell.AgeProperty, "Age");
customCell.SetBinding (CustomCell.LocationProperty, "Location");
var listView = new ListView {
ItemsSource = people,
ItemTemplate = customCell
};
在iOS和Android上,如果ListView
是循環元素,並且自定義單元格使用自定義渲染器,則自定義渲染器必須正確實現屬性更改通知。當重新使用單元格時,當綁定上下文更新爲可用單元格的屬性值時,其屬性值將更改,並PropertyChanged
引發事件。有關詳細信息,請參閱自定義ViewCell。有關細胞再循環的更多信息,請參閱緩存策略。
在Android上啓用行選擇
爲了允許對包含諸如按鈕之類的輸入元素的單元格進行行選擇,需要簡單custom
renderer
。在通用代碼中,創建一個子類,Button
以便在平臺項目中添加自定義渲染器:
public class ListButton : Button { }
Android的渲染器實現只需設置Focusable
允許行可選擇的屬性以及可主機可點擊的按鈕。此代碼已添加到Android應用程序項目中:
[assembly: ExportRenderer (typeof (ListButton), typeof (ListButtonRenderer))]
// ...
public class ListButtonRenderer : ButtonRenderer {
protected override void OnElementChanged (ElementChangedEventArgs<ListButton> e) {
base.OnElementChanged (e);
Control.Focusable = false;
}
}
如上所述,只有Android需要ButtonRenderer
實現。iOS和Windows Phone平臺都允許單擊按鈕,而不實現自定義渲染器。