自定義 ListView 儲存格外觀

類別 Xamarin.FormsListView 可用來呈現可捲動的清單,這些清單可透過元素的使用 ViewCell 來自定義。 元素 ViewCell 可以顯示文字和影像、指出 true/false 狀態,以及接收用戶輸入。

內建單元格

Xamarin.Forms 隨附適用於許多應用程式的內建資料格:

  • TextCell 控件用於顯示具有詳細數據文字之選擇性第二行的文字。
  • ImageCell 控件類似於 TextCells,但包含文字左邊的影像。
  • SwitchCell 控件可用來呈現和擷取開啟/關閉或 true/false 狀態。
  • EntryCell 控制件可用來呈現使用者可以編輯的文字數據。

SwitchCellEntryCell 控件在的內容TableView中較常用。

TextCell

TextCell 是用來顯示文字的儲存格,選擇性地以第二行做為詳細數據文字。 下列螢幕快照顯示 TextCell iOS 和 Android 上的專案:

默認 TextCell 範例

TextCells 會在運行時間轉譯為原生控件,因此相較於自定義 ViewCell,效能非常好。 TextCells 是可自定義的,可讓您設定下列屬性:

  • Text – 第一行顯示的文字,以大字型顯示。
  • Detail – 以較小的字型顯示於第一行下方的文字。
  • TextColor – 文字的色彩。
  • DetailColor – 詳細數據文字的色彩

下列螢幕快照顯示 TextCell 具有自訂色彩屬性的專案:

自定義 TextCell 範例

ImageCell

ImageCell例如 TextCell,可用來顯示文字和次要詳細數據文字,而且使用每個平臺的原生控件提供絕佳的效能。 ImageCellTextCell不同於 ,它會顯示文字左邊的影像。

下列螢幕快照顯示 ImageCell iOS 和 Android 上的專案: “Default ImageCell 範例”

ImageCell 當您需要以視覺層面顯示數據清單,例如聯繫人或電影清單時,會很有用。 ImageCells 是可自定義的,可讓您設定:

  • Text – 以大字型顯示在第一行的文字
  • Detail – 以較小的字型顯示於第一行下方的文字
  • TextColor – 文字的色彩
  • DetailColor – 詳細數據文字的色彩
  • ImageSource – 要顯示在文字旁的影像

下列螢幕快照顯示 ImageCell 具有自訂色彩屬性的專案: “自定義 ImageCell 範例”

自定義儲存格

自定義儲存格可讓您建立內建單元格不支援的儲存格配置。 例如,您可能想要呈現具有兩個具有相等權數卷標的單元格。 TextCell會不足,TextCell因為 有一個較小的標籤。 大部分的數據格自定義都會新增其他唯讀數據(例如其他標籤、影像或其他顯示資訊)。

所有自定義儲存格都必須衍生自 ViewCell,這是所有內建單元格類型所使用的相同基類。

Xamarin.Forms提供控件的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,配置可由任何 Xamarin.Forms 版面配置管理。 在此範例中,配置是由 管理 StackLayout,可自定義背景色彩。

注意

任何可系結的屬性 StackLayout 都可以系結在自定義單元格內。 不過,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 的 ItemTemplate 屬性會設定為 DataTemplate 具有指定型別的 CustomCell

public partial class ImageCellPage : ContentPage
    {
        public ImageCellPage ()
        {
            InitializeComponent ();
            listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
        }
    }

系結內容變更

系結至自定義數據格類型的 BindableProperty 實例時,顯示 BindableProperty 值的 UI 控件應該使用 OnBindingContextChanged 覆寫來設定要在每個單元格中顯示的數據,而不是單元格建構函式,如下列程式代碼範例所示:

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實例中的 CustomCellAgeLocation 可系結屬性系結至Name基礎集合中每個物件的、 AgeLocation 屬性。

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。 如需儲存格回收的詳細資訊,請參閱 快取策略