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; }
}
次のスクリーンショットは、一覧表内の各項目をテンプレート化した結果を示しています。
データ テンプレートの詳細については、「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
および OtherMonkey
DataTemplate
プロパティを定義します。 OnSelectTemplate
オーバーライドは、AmericanMonkey
テンプレートを返します。このテンプレートでは、サルの名前に「America」が含まれている場合、サルの名前と場所が青緑で表示されます。 サルの名前に「America」が含まれていない場合、OnSelectTemplate
オーバーライドは OtherMonkey
テンプレートを返し、サルの名前と場所が銀色で表示されます。
データ テンプレート セレクターの詳細については、「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
コンテンツでアクションを実行するために使用され、コントロールを左側からスワイプすると表示されます。
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
が実行され、表示中の項目が更新されます。 更新が行われている間、更新の視覚化が進行状況円のアニメーションとして表示されます。
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
実装にバインドすれば、データを増分読み込みすることもできます。