CollectionView へのデータの入力
.NET Multi-Platform App UI (.NET MAUI) の CollectionView には、表示するデータとその外観を定義する次のプロパティが含まれています。
IEnumerable
型のItemsSource
は、表示される項目のコレクションを指定します。既定値はnull
です。- DataTemplate 型の
ItemTemplate
は、表示される項目のコレクション内の、各項目に適用するテンプレートを指定します。
これらのプロパティはすべて、BindableProperty オブジェクトを基盤としています。つまり、プロパティをデータ バインディングの対象にすることができます。
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
コンパイル済みバインドを有効にすると、.NET MAUI アプリケーションのデータ バインディングのパフォーマンスを向上させることができます。 詳しくは、「コンパイル済みのバインド」を参照してください。
CollectionView のレイアウトを変更する方法については、「CollectionView レイアウトの指定」をご覧ください。 CollectionView 内の各項目の外観を定義する方法については、「項目の外観を定義する」をご覧ください。 データ バインディングの詳細については、「 データ バインディング」をご覧ください。
警告
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.Add(image);
grid.Add(nameLabel, 1, 0);
grid.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; }
}
次のスクリーンショットは、リスト内の各項目をテンプレート化した結果を示しています。
ヒント
VerticalStackLayout の中に CollectionView を置くと、CollectionView のスクロールを停止し、表示される項目の数を制限できます。 このような場合は、VerticalStackLayout を Grid に置き換えます。
データ テンプレートの詳細については、「データ テンプレート」をご覧ください。
実行時にアイテムの外観を選択
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
および OtherMonkey
DataTemplate プロパティを定義します。 OnSelectTemplate
オーバーライドは、AmericanMonkey
テンプレートを返します。このテンプレートでは、サルの名前に「America」が含まれている場合、サルの名前と場所が青緑で表示されます。 サルの名前に「America」が含まれていない場合、OnSelectTemplate
オーバーライドは OtherMonkey
テンプレートを返し、サルの名前と場所が銀色で表示されます。
データ テンプレート セレクターの詳細については、「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 = Colors.White };
// ...
SwipeView swipeView = new SwipeView();
SwipeItem favoriteSwipeItem = new SwipeItem
{
Text = "Favorite",
IconImageSource = "favorite.png",
BackgroundColor = Colors.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 = Colors.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 コンテンツでアクションを実行するために使用され、コントロールを左側からスワイプすると表示されます。
SwipeView では、4 つの異なるスワイプ方向がサポートされ、スワイプ方向は、SwipeItems
オブジェクトが追加される方向 SwipeItems
コレクションによって定義されます。 既定では、ユーザーにタップされるとスワイプ項目が実行されます。 さらに、スワイプ項目が実行されると、スワイプ項目は非表示になり、SwipeView コンテンツが再表示されます。 ただし、これらの動作は変更できます。
SwipeView コントロールの詳細については、「SwipeView」を参照してください。
引っ張って更新
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 が実行され、表示中の項目が更新されます。 更新が行われている間、更新の視覚化が進行状況円のアニメーションとして表示されます。
RefreshView.IsRefreshing
プロパティの値は、RefreshView の現在の状態を示します。 ユーザーによって更新がトリガーされると、このプロパティは自動的に true
に切り替わります。 更新が完了したら、プロパティを false
にリセットする必要があります。
RefreshView の詳細については、「 RefreshView」を参照してください。
データを増分読み込みする
CollectionView では、ユーザーによるスクロール時の増分データ仮想化をサポートしています。 これにより、ユーザーがスクロールするにつれて、Web サービスからデータのページを非同期的に読み込むなどのシナリオが可能になります。 さらに、ユーザーに空白が表示されないように、またはユーザーがスクロールする気にならないように、より多くのデータが読み込まれる時点を構成できます。
警告
StackLayout 内の CollectionView でデータの増分読み込みを試みないでください。 このシナリオでは、CollectionView が拡張し続ける無限ループが発生します。
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 実装にバインドすれば、データを増分読み込みすることもできます。
.NET MAUI