Share via


Xamarin.FormsCollectionView のデータ

CollectionView には、表示されるデータとその外観を定義する次のプロパティが含まれます。

  • IEnumerable 型の ItemsSource は、表示される項目のコレクションを指定します。既定値は null です。
  • DataTemplate 型の ItemTemplate は、表示される項目のコレクション内の、各項目に適用するテンプレートを指定します。

これらのプロパティはすべて、BindableProperty オブジェクトを基盤としています。つまり、プロパティをデータ バインディングの対象にすることができます。

Note

CollectionView には、新しい項目が追加されたときの CollectionView のスクロール動作を表す ItemsUpdatingScrollMode プロパティが定義されています。 このプロパティの詳細については、「新しい項目が追加されたときのスクロール位置の制御」を参照してください。

CollectionView では、ユーザーによるスクロール時の増分データ仮想化をサポートしています。 詳細については、「増分データ読み込み」を参照してください。

CollectionView へのデータの入力

CollectionView にデータを入力するには、その ItemsSource プロパティを、IEnumerable を実装する任意のコレクションに設定します。 既定では、CollectionView には項目が縦書きリストで表示されます。

重要

基になるコレクションで項目が追加、削除、または変更されたときに CollectionView を更新する必要がある場合、基になるコレクションは、ObservableCollection などのプロパティ変更通知を送信する IEnumerable コレクションである必要があります。

CollectionView には、データ バインディングを使用して ItemsSource プロパティを IEnumerable コレクションにバインドすることでデータを設定できます。 XAML でこれを実行するには、Binding マークアップ拡張を使用します。

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

同等の C# コードを次に示します。

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

この例では、ItemsSource プロパティ データは、接続されたビューモデルの Monkeys プロパティにバインドされます。

Note

コンパイル済みのバインドを有効にして、Xamarin.Forms アプリケーションでのデータ バインディングのパフォーマンスを改善できます。 詳しくは、「コンパイル済みのバインディング」を参照してください。

CollectionView レイアウトを変更する方法については、「Xamarin.FormsCollectionView レイアウト」参照してください。 CollectionView 内の各項目の外観を定義する方法については、「項目の外観を定義する」をご覧ください。 データ バインディングの詳細については、「Xamarin.Forms のデータ バインディング」を参照してください。

警告

CollectionView は、ItemsSource が UI スレッドから更新された場合に例外をスローします。

項目の外観を定義

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 内のレイアウトは Grid によって管理されています。 Grid には、Image オブジェクトと 2 つの Label オブジェクトが含まれており、これらはすべて Monkey クラスのプロパティにバインドされています。

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

次のスクリーンショットは、一覧表内の各項目をテンプレート化した結果を示しています。

iOS と Android 上での各項目がテンプレート化されている CollectionView のスクリーンショット

データ テンプレートの詳細については、「Xamarin.Forms のデータ テンプレート」を参照してください。

実行時にアイテムの外観を選択

CollectionView.ItemTemplate プロパティを DataTemplateSelector オブジェクトに設定することで、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;
    }
}

MonkeyDataTemplateSelector クラスは、さまざまなデータ テンプレートに設定される AmericanMonkey プロパティと OtherMonkeyDataTemplate プロパティを定義します。 OnSelectTemplate オーバーライドは、AmericanMonkey テンプレートを返します。このテンプレートでは、サルの名前に「America」が含まれている場合、サルの名前と場所が青緑で表示されます。 サルの名前に「America」が含まれていない場合、OnSelectTemplate オーバーライドは OtherMonkey テンプレートを返し、サルの名前と場所が銀色で表示されます。

iOS と Android 上での CollectionView ランタイム項目テンプレート選択のスクリーンショット

データ テンプレート セレクターの詳細については、「Xamarin.Forms DataTemplateSelector の作成」を参照してください。

重要

CollectionView を使用する場合は、DataTemplate オブジェクトのルート要素を ViewCell に設定しないでください。 CollectionView にはセルの概念がないので、例外がスローされます。

コンテキスト メニュー

CollectionView では、スワイプ ジェスチャでコンテキスト メニューを表示する SwipeView を通じて、データ項目のコンテキスト メニューをサポートしています。 SwipeView は、コンテンツ項目をラップし、そのコンテンツ項目のコンテキスト メニュー項目を提供するコンテナー コントロールです。 したがって、CollectionView にコンテキスト メニューを実装するには、SwipeView でラップするコンテンツと、スワイプ ジェスチャで表示されるコンテキスト メニュー項目を定義する SwipeView を作成します。 これは、CollectionView 内の各データ項目の外観を定義する DataTemplate のルート ビューとして SwipeView を設定することで実現されます 。

<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 コンテンツは、CollectionView 内の各項目の外観を定義する Grid です。 スワイプ項目は、SwipeView コンテンツでアクションを実行するために使用され、コントロールを左側からスワイプすると表示されます。

iOS と Android 上での CollectionView ショートカット メニュー項目のスクリーンショット

SwipeView では、4 つの異なるスワイプ方向がサポートされ、スワイプ方向は、SwipeItems オブジェクトが追加される方向 SwipeItems コレクションによって定義されます。 既定では、ユーザーにタップされるとスワイプ項目が実行されます。 さらに、スワイプ項目が実行されると、スワイプ項目は非表示になり、SwipeView コンテンツが再表示されます。 ただし、これらの動作は変更できます。

SwipeView コントロールの詳細については、「Xamarin.FormsSwipeView」を参照してください。

引っ張って更新

CollectionView では、RefreshView を通じて "引っ張って更新" 機能をサポートしています。これにより、項目リストをプルダウンして表示中のデータを更新できます。 RefreshView は、スクロール可能なコンテンツを子がサポートしている場合に、その子に "引っ張って更新" 機能を提供するコンテナー コントロールです。 したがって、"引っ張って更新" を CollectionView に実装するには、そのオブジェクトを RefreshView の子として設定します。

<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;
// ...

ユーザーが更新を開始すると、Command プロパティで定義されている ICommand が実行され、表示中の項目が更新されます。 更新が行われている間、更新の視覚化が進行状況円のアニメーションとして表示されます。

iOS と Android 上での CollectionView の引っ張って更新のスクリーンショット

RefreshView.IsRefreshing プロパティの値は、RefreshView の現在の状態を示します。 ユーザーによって更新がトリガーされると、このプロパティは自動的に true に切り替わります。 更新が完了したら、プロパティを false にリセットする必要があります。

RefreshView の詳細については、「Xamarin.Forms RefreshView」を参照してください。

データを増分読み込みする

CollectionView では、ユーザーによるスクロール時の増分データ仮想化をサポートしています。 これにより、ユーザーがスクロールするにつれて、Web サービスからデータのページを非同期的に読み込むなどのシナリオが可能になります。 さらに、ユーザーに空白が表示されないように、またはユーザーがスクロールする気にならないように、より多くのデータが読み込まれる時点を構成できます。

CollectionView には、データの増分読み込みを制御するための次のプロパティが定義されています。

  • RemainingItemsThreshold (int 型): RemainingItemsThresholdReached イベントの発生時にリストにまだ表示されていない項目のしきい値。
  • RemainingItemsThresholdReachedCommand (ICommand 型): RemainingItemsThreshold に達したときに実行されます。
  • RemainingItemsThresholdReachedCommandParameter: object 型、RemainingItemsThresholdReachedCommand に渡されるパラメーター。

また、CollectionView には、RemainingItemsThresholdReached 個の項目がまだ表示されないほど CollectionView がスクロールされると発生する RemainingItemsThreshold イベントも定義されています。 このイベントを処理して、さらに多くの項目を読み込むことができます。 さらに、RemainingItemsThresholdReached イベントが 発生すると、RemainingItemsThresholdReachedCommand が実行され、ビューモデルで増分データ読み込みを行えるようになります。

RemainingItemsThreshold プロパティの 既定値は -1 です。これは、RemainingItemsThresholdReached イベントが発生しないことを示します。 このプロパティ値が 0 の場合、RemainingItemsThresholdReached イベントは、ItemsSource 内の最後の項目が表示されたときに発生します。 0 より大きい値の場合は、まだそこまでスクロールされていない項目が ItemsSource にその数だけ含まれていると RemainingItemsThresholdReached イベントが発生します。

Note

CollectionView は、RemainingItemsThreshold プロパティの値が常に -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");

このコード例では、5 つの項目までまだスクロールされていないと RemainingItemsThresholdReached イベントが発生し、その応答として OnCollectionViewRemainingItemsThresholdReached イベント ハンドラーが実行されます。

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

Note

RemainingItemsThresholdReachedCommand をビューモデルの ICommand 実装にバインドすれば、データを増分読み込みすることもできます。