Xamarin.Forms CollectionView 數據

Download Sample 下載範例

CollectionView 包含下列屬性,可定義要顯示的數據及其外觀:

  • ItemsSourceIEnumerable別為 的 ,指定要顯示的專案集合,且預設值為 null
  • ItemTemplate類型 DataTemplate為 的 ,指定要套用至要顯示之專案集合中每個專案的範本。

這些屬性是由 BindableProperty 物件所支援,這表示屬性可以是數據系結的目標。

注意

CollectionViewItemsUpdatingScrollMode 定義 屬性,這個屬性表示將新專案加入至其中時的 CollectionView 捲動行為。 如需此屬性的詳細資訊,請參閱 新增專案時控制卷動位置。

CollectionView 當使用者捲動時,支援累加式數據虛擬化。 如需詳細資訊,請參閱 以累加方式載入數據。

使用數據填入 CollectionView

會將 CollectionViewItemsSource 屬性設定為任何實作 的 IEnumerable集合,以填入數據。 根據預設, CollectionView 會在垂直清單中顯示專案。

重要

CollectionView如果需要在基礎集合中新增、移除或變更專案時重新整理 ,基礎集合應該是IEnumerable傳送屬性變更通知的集合,例如 ObservableCollection

CollectionView 您可以使用數據系結將其屬性系結 ItemsSourceIEnumerable 集合,以填入數據。 在 XAML 中,這會透過 Binding 標記延伸來達成:

<CollectionView ItemsSource="{Binding Monkeys}" />

對等的 C# 程式碼為:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

在此範例中 ItemsSource ,屬性數據會系結至 Monkeys 連接的 ViewModel 屬性。

注意

您可以啟用編譯的系結,以改善應用程式中的數據系結效能 Xamarin.Forms 。 如需詳細資訊,請參閱編譯繫結

如需如何變更版面 CollectionView 配置的資訊,請參閱 Xamarin.Forms CollectionView 版面配置。 如需如何定義 中 CollectionView每個項目外觀的資訊,請參閱 定義項目外觀。 如需數據系結的詳細資訊,請參閱 Xamarin.Forms 數據系結

警告

CollectionView 如果在UI線程之外更新例外 ItemsSource 狀況,則會擲回例外狀況。

定義項目外觀

中每個項目 CollectionView 的外觀都可以藉由將 屬性設定 CollectionView.ItemTemplate 為 來 DataTemplate定義:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
    ...
</CollectionView>

對等的 C# 程式碼為:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

collectionView.ItemTemplate = new DataTemplate(() =>
{
    Grid grid = new Grid { Padding = 10 };
    grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
    grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

    Image image = new Image { Aspect = Aspect.AspectFill, HeightRequest = 60, WidthRequest = 60 };
    image.SetBinding(Image.SourceProperty, "ImageUrl");

    Label nameLabel = new Label { FontAttributes = FontAttributes.Bold };
    nameLabel.SetBinding(Label.TextProperty, "Name");

    Label locationLabel = new Label { FontAttributes = FontAttributes.Italic, VerticalOptions = LayoutOptions.End };
    locationLabel.SetBinding(Label.TextProperty, "Location");

    Grid.SetRowSpan(image, 2);

    grid.Children.Add(image);
    grid.Children.Add(nameLabel, 1, 0);
    grid.Children.Add(locationLabel, 1, 1);

    return grid;
});

中指定的 DataTemplate 項目會定義清單中每個項目的外觀。 在此範例中,內的 DataTemplate 版面配置是由 管理 GridGrid包含物件和兩LabelImage 物件,這些物件都系結至 類別的屬性Monkey

public class Monkey
{
    public string Name { get; set; }
    public string Location { get; set; }
    public string Details { get; set; }
    public string ImageUrl { get; set; }
}

下列螢幕快照顯示範本化清單中每個項目的結果:

Screenshot of CollectionView where each item is templated, on iOS and Android

如需數據範本的詳細資訊,請參閱 Xamarin.Forms 數據範本

選擇運行時間的項目外觀

您可以藉由將 屬性DataTemplateSelector設定CollectionView.ItemTemplate為物件,在執行時間根據專案值,選擇 中CollectionView每個項目的外觀:

<ContentPage ...
             xmlns:controls="clr-namespace:CollectionViewDemos.Controls">
    <ContentPage.Resources>
        <DataTemplate x:Key="AmericanMonkeyTemplate">
            ...
        </DataTemplate>

        <DataTemplate x:Key="OtherMonkeyTemplate">
            ...
        </DataTemplate>

        <controls:MonkeyDataTemplateSelector x:Key="MonkeySelector"
                                             AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
                                             OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
    </ContentPage.Resources>

    <CollectionView ItemsSource="{Binding Monkeys}"
                    ItemTemplate="{StaticResource MonkeySelector}" />
</ContentPage>

對等的 C# 程式碼為:

CollectionView collectionView = new CollectionView
{
    ItemTemplate = new MonkeyDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

屬性 ItemTemplate 會設定為 MonkeyDataTemplateSelector 物件。 下列範例顯示 類別 MonkeyDataTemplateSelector

public class MonkeyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate AmericanMonkey { get; set; }
    public DataTemplate OtherMonkey { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
    }
}

類別 MonkeyDataTemplateSelectorAmericanMonkey 定義 和 OtherMonkeyDataTemplate 屬性,這些屬性會設定為不同的數據範本。 覆寫會 OnSelectTemplateAmericanMonkey 回範本,當猴子名稱包含 「America」 時,它會在 teal 中顯示猴子名稱和位置。 當猴子名稱不包含 「America」 時, OnSelectTemplate 覆寫會 OtherMonkey 傳回範本,以銀為單位顯示猴子名稱和位置:

Screenshot of CollectionView runtime item template selection, on iOS and Android

如需數據範本選取器的詳細資訊,請參閱 建立 Xamarin.Forms DataTemplateSelector

重要

使用 CollectionView時,永遠不要將 物件的根元素 DataTemplate 設定為 ViewCell。 這會導致擲回例外狀況,因為 CollectionView 沒有單元格的概念。

操作功能表

CollectionView 支援透過 SwipeView的數據項操作功能表,其會顯示具有撥動手勢的操作功能表。 SwipeView是包裝內容專案的容器控件,並提供該內容專案的操作功能表項。 因此,藉由建立 SwipeView ,定義包裝的內容SwipeView,以及撥動手勢所顯示的內容功能表項,即可實CollectionView作 操作功能表。 這可藉由將 設定 SwipeView 為 中 DataTemplate 定義中每個資料 CollectionView項目外觀的 根檢視來達成此目的:

<CollectionView x:Name="collectionView"
                ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <SwipeView>
                <SwipeView.LeftItems>
                    <SwipeItems>
                        <SwipeItem Text="Favorite"
                                   IconImageSource="favorite.png"
                                   BackgroundColor="LightGreen"
                                   Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}"
                                   CommandParameter="{Binding}" />
                        <SwipeItem Text="Delete"
                                   IconImageSource="delete.png"
                                   BackgroundColor="LightPink"
                                   Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}"
                                   CommandParameter="{Binding}" />
                    </SwipeItems>
                </SwipeView.LeftItems>
                <Grid BackgroundColor="White"
                      Padding="10">
                    <!-- Define item appearance -->
                </Grid>
            </SwipeView>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

對等的 C# 程式碼為:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

collectionView.ItemTemplate = new DataTemplate(() =>
{
    // Define item appearance
    Grid grid = new Grid { Padding = 10, BackgroundColor = Color.White };
    // ...

    SwipeView swipeView = new SwipeView();
    SwipeItem favoriteSwipeItem = new SwipeItem
    {
        Text = "Favorite",
        IconImageSource = "favorite.png",
        BackgroundColor = Color.LightGreen
    };
    favoriteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.FavoriteCommand", source: collectionView));
    favoriteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");

    SwipeItem deleteSwipeItem = new SwipeItem
    {
        Text = "Delete",
        IconImageSource = "delete.png",
        BackgroundColor = Color.LightPink
    };
    deleteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.DeleteCommand", source: collectionView));
    deleteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");

    swipeView.LeftItems = new SwipeItems { favoriteSwipeItem, deleteSwipeItem };
    swipeView.Content = grid;    
    return swipeView;
});

在這裡範例中 SwipeView ,內容是定義 Grid 中每個項目外觀的 CollectionView。 撥動專案可用來對 SwipeView 內容執行動作,並在控制件從左側撥動時顯示:

Screenshot of CollectionView context menu items, on iOS and Android

SwipeView 支援四個不同的撥動方向,而撥動方向是由物件新增至的方向 SwipeItems 集合 SwipeItems 所定義。 根據預設,撥動專案會在用戶點選時執行。 此外,一旦執行撥動專案,撥動專案就會隱藏並 SwipeView 重新顯示內容。 不過,這些行為可以變更。

如需控件的詳細資訊 SwipeView ,請參閱 Xamarin.Forms SwipeView

提取以重新整理

CollectionView 支援透過 RefreshView來重新整理功能,藉由向下拉下專案清單,讓顯示的數據重新整理。 RefreshView是一個容器控件,提供提取來重新整理其子系的功能,前提是子系支援可捲動的內容。 因此,藉由將提取重新整理設定為 的RefreshView子系,會針對 CollectionView 實作 :

<RefreshView IsRefreshing="{Binding IsRefreshing}"
             Command="{Binding RefreshCommand}">
    <CollectionView ItemsSource="{Binding Animals}">
        ...
    </CollectionView>
</RefreshView>

對等的 C# 程式碼為:

RefreshView refreshView = new RefreshView();
ICommand refreshCommand = new Command(() =>
{
    // IsRefreshing is true
    // Refresh data here
    refreshView.IsRefreshing = false;
});
refreshView.Command = refreshCommand;

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
refreshView.Content = collectionView;
// ...

當使用者起始重新整理時, ICommand 會執行 屬性所 Command 定義的 ,這應該會重新整理要顯示的專案。 重新整理發生時會顯示重新整理視覺效果,其中包含動畫進度圓形:

Screenshot of CollectionView pull-to-refresh, on iOS and Android

屬性的值 RefreshView.IsRefreshing 表示 的 RefreshView目前狀態。 當使用者觸發重新整理時,這個屬性會自動轉換為 true。 重新整理完成後,您應該將 屬性 false重設為 。

如需 的詳細資訊 RefreshView,請參閱 Xamarin.Forms RefreshView

以累加方式載入數據

CollectionView 當使用者捲動時,支援累加式數據虛擬化。 這可讓使用者捲動時,以異步方式從 Web 服務載入數據頁面等案例。 此外,可以設定載入更多資料的時間點,讓使用者看不到空白,或停止捲動。

CollectionView 定義下列屬性來控制資料的累加式載入:

  • RemainingItemsThreshold類型 int為 的 ,表示清單中尚未顯示 RemainingItemsThresholdReached 要引發事件的項目臨界值。
  • RemainingItemsThresholdReachedCommand,類型 ICommand為 ,會在 到達時 RemainingItemsThreshold 執行。
  • RemainingItemsThresholdReachedCommandParameter,屬於 object 類型,這是傳遞至 RemainingItemsThresholdReachedCommand 的參數。

CollectionView也會定義RemainingItemsThresholdReached在捲動到足以RemainingItemsThreshold顯示項目時CollectionView引發的事件。 此事件可以處理以載入更多專案。 此外,在引發事件時 RemainingItemsThresholdReachedRemainingItemsThresholdReachedCommand 會執行 ,讓累加式數據載入在 viewmodel 中執行。

屬性的 RemainingItemsThreshold 預設值為 -1,表示 RemainingItemsThresholdReached 永遠不會引發事件。 當屬性值為 0 時, RemainingItemsThresholdReached 會在 顯示 中的 ItemsSource 最後一個項目時引發 事件。 對於大於 0 的值,當 包含尚未捲動的項目數目時ItemsSourceRemainingItemsThresholdReached就會引發 事件。

注意

CollectionViewRemainingItemsThreshold 驗證 屬性,使其值一律大於或等於 -1。

下列 XAML 範例示範 CollectionView 以累加方式載入資料的 :

<CollectionView ItemsSource="{Binding Animals}"
                RemainingItemsThreshold="5"
                RemainingItemsThresholdReached="OnCollectionViewRemainingItemsThresholdReached">
    ...
</CollectionView>

對等的 C# 程式碼為:

CollectionView collectionView = new CollectionView
{
    RemainingItemsThreshold = 5
};
collectionView.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");

在此程式代碼範例中 RemainingItemsThresholdReached ,事件會在有5個專案尚未捲動時引發,而回應中會 OnCollectionViewRemainingItemsThresholdReached 執行事件處理程式:

void OnCollectionViewRemainingItemsThresholdReached(object sender, EventArgs e)
{
    // Retrieve more data here and add it to the CollectionView's ItemsSource collection.
}

注意

您也可以藉由將 系結 RemainingItemsThresholdReachedCommandICommand viewmodel 中的實作,以累加方式載入數據。