ListView
.NET マルチプラットフォーム アプリ UI (.NET MAUI) ListView では、選択可能なデータ項目がスクロール可能な縦型のリストで表示されます。 ListView がリストの外観を管理する一方で、リスト内の各項目の外観は、Cell を使って項目を表示する DataTemplate によって定義されます。 .NET MAUI には、テキストと画像の組み合わせを表示するセルの種類があり、必要なコンテンツを表示するカスタム セルを定義することもできます。 ListView では、ヘッダーとフッター、グループ化されたデータ、プルから更新、コンテキスト メニュー項目の表示もサポートされています。
ListView クラスは ItemsView<Cell>
クラスから派生し、そこから次のプロパティを継承します。
IEnumerable
型のItemsSource
は、表示される項目のコレクションを指定します。既定値はnull
です。- DataTemplate 型の
ItemTemplate
は、表示される項目のコレクション内の、各項目に適用するテンプレートを指定します。
ListView には、次のプロパティが定義されています。
object
型のFooter
は、リストの末尾に表示される文字列またはビューを指定します。- DataTemplate 型の
FooterTemplate
は、Footer
の書式を設定するために使用する DataTemplate を指定します。 - DataTemplate 型の
GroupHeaderTemplate
は、各グループのヘッダーの外観を定義するために使用する DataTemplate を定義します。 このプロパティとGroupDisplayBinding
プロパティは、同時には有効にできません。 そのため、このプロパティを設定すると、GroupDisplayBinding
がnull
に設定されます。 bool
型のHasUnevenRows
は、リスト内の項目に異なる高さの行を含めることができるかどうかを示します。 このプロパティの既定値はfalse
です。object
型のHeader
は、リストの先頭に表示される文字列またはビューを指定します。- DataTemplate 型の
HeaderTemplate
は、Header
の書式を設定するために使用する DataTemplate を指定します。 ScrollBarVisibility
型のHorizontalScrollBarVisibility
は、水平スクロール バーが表示されるタイミングを示します。bool
型のIsGroupingEnabled
は、基になるデータをグループに表示するかどうかを示します。 このプロパティの既定値はfalse
です。bool
型のIsPullToRefreshEnabled
は、ユーザーが下にスワイプして ListView がデータを更新できるかどうかを示します。 このプロパティの既定値はfalse
です。bool
型のIsRefreshing
は、ListView が現在更新されているかどうかを示します。 このプロパティの既定値はfalse
です。- ICommand 型の
RefreshCommand
は、更新がトリガーされたときに実行されるコマンドを表します。 - Color 型の
RefreshControlColor
は、更新の実行中に表示される更新ビジュアライゼーションの色を決定します。 int
型のRowHeight
は、HasUnevenRows
がfalse
の場合に各行の高さを決定します。object
型のSelectedItem
は、ListView で現在選択されている項目を表します。ListViewSelectionMode
型のSelectionMode
は、ListView で項目を選択できるかどうかを示します。 このプロパティの既定値はSingle
です。- Color 型の
SeparatorColor
は、リスト内の項目を区切るバーの色を定義します。 SeparatorVisibility
型のSeparatorVisibility
は、項目間で区切り記号を表示するかどうかを定義します。ScrollBarVisibility
型のVerticalScrollBarVisibility
は、垂直スクロール バーが表示されるタイミングを示します。
これらのプロパティはすべて BindableProperty オブジェクトが基になっています。つまり、データ バインディングの対象にすることができ、スタイルを設定できます。
さらに、ListView は、BindableProperty オブジェクトによってサポートされていない次のプロパティを定義します。
BindingBase
型のGroupDisplayBinding
は、グループ ヘッダーの表示に使用するバインディングです。 このプロパティとGroupHeaderTemplate
プロパティは、同時には有効にできません。 そのため、このプロパティを設定すると、GroupHeaderTemplate
がnull
に設定されます。BindingBase
型のGroupShortNameBinding
は、グループ化されたジャンプ リストに表示する名前のバインディングです。ListViewCachingStrategy
型のCachingStrategy
は、ListView のセルの再利用戦略を定義します 。 これは、読み取り専用プロパティです。
ListView は、次のイベントを定義します。
ItemAppearing
は、項目の視覚的な表現が、ListView の視覚的なレイアウトに追加されているときに発生します。 このイベントに付随するItemVisibilityEventArgs
オブジェクトは、Item
プロパティとIndex
プロパティを定義します。ItemDisappearing
は、項目の視覚的な表現が、ListView の視覚的なレイアウトから削除されているときに発生します。 このイベントに付随するItemVisibilityEventArgs
オブジェクトは、Item
プロパティとIndex
プロパティを定義します。ItemSelected
は、リスト内の新しい項目が選択されたときに発生します。 このイベントに付随するSelectedItemChangedEventArgs
オブジェクトは、SelectedItem
プロパティとSelectedItemIndex
プロパティを定義します。ItemTapped
は、ListView 内の項目がタップされたときに発生します。 このイベントに付随するItemTappedEventArgs
オブジェクトは、Group
プロパティ、Item
プロパティ、ItemIndex
プロパティを定義します。Refreshing
は、ListView で更新するプル操作がトリガーされたときに発生します。Scrolled
, . このイベントに付随するScrolledEventArgs
オブジェクトは、ScrollX
プロパティとScrollY
プロパティを定義します。ScrollToRequested
このイベントに付随するScrollToRequestedEventArgs
オブジェクトは、Element プロパティ、Mode
プロパティ、Position
プロパティ、ScrollX
プロパティ、ScrollY
プロパティ、ShouldAnimate
プロパティを定義します。
ListView にデータを読み込む
ListView にデータを入力するには、IEnumerable
を実装するコレクションに ItemsSource
プロパティを設定します。
重要
基になるコレクションで項目が追加、削除、または変更されたときに ListView を更新する必要がある場合、基になるコレクションは、ObservableCollection
などのプロパティ変更通知を送信する IEnumerable
コレクションである必要があります。
ListView には、データ バインディングを使用して ItemsSource
プロパティを IEnumerable
コレクションにバインドすることでデータを設定できます。 XAML でこれを実行するには、Binding
マークアップ拡張を使用します。
<ListView ItemsSource="{Binding Monkeys}" />
同等の C# コードを次に示します。
ListView listView = new ListView();
listView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
この例では、ItemsSource
プロパティ データは、接続されたビューモデルの Monkeys
プロパティにバインドされます。
Note
コンパイル済みバインドを有効にすると、.NET MAUI アプリケーションのデータ バインディングのパフォーマンスを向上させることができます。 詳しくは、「コンパイル済みのバインド」を参照してください。
データ バインディングの詳細については、「 データ バインディング」をご覧ください。
項目の外観を定義
ListView 内の各項目の外観は、ItemTemplate
プロパティを DataTemplate に設定することで定義できます。
<ListView ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<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>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
リスト内の各項目の外観は DataTemplate で指定された要素で定義され、DataTemplate の子は Cell オブジェクトである必要があります。 この例では、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; }
}
次のスクリーンショットは、リスト内の各項目をテンプレート化した結果を示しています。
データ テンプレートの詳細については、「データ テンプレート」をご覧ください。
セル
ListView 内の各項目の外観は DataTemplate によって定義され、DataTemplate は項目を表示するために Cell クラスを参照する必要があります。 各セルは、ListView 内のデータ項目を表します。 .NET MAUI には、次の組み込みセルが含まれています。
- TextCell は、プライマリ テキストとセカンダリ テキストを別々の行に表示します。
- ImageCell は、プライマリ テキストとセカンダリ テキストとともに画像を別々の行に表示します。
- SwitchCell は、テキストと、オンまたはオフに切り替えることができるスイッチを表示します。
- EntryCell は、編集可能なラベルとテキストを表示します。
- ViewCell は、外観が View で定義されているカスタム セルです。 このセル タイプは、ListView 内の各項目の外観を完全に定義する場合に使用する必要があります。
通常、SwitchCell と EntryCell は TableView でのみ使用され、ListView では使用されません。 SwitchCell と EntryCell の詳細については、「TableView」を参照してください。
テキストのセル
TextCell は、プライマリ テキストとセカンダリ テキストを別々の行に表示します。 TextCell には、次のプロパティが定義されています。
string
型のText
は、表示するプライマリ テキストを定義します。- Color 型の
TextColor
は、プライマリ テキストの色を表します。 string
型のDetail
は、表示するセカンダリ テキストを定義します。- Color 型の
DetailColor
は、セカンダリ テキストの色を表します。 - ICommand 型の
Command
は、セルがタップされたときに実行されるコマンドを定義します。 object
型のCommandParameter
は、コマンドに渡されるパラメーターを表します。
これらのプロパティは、BindableProperty オブジェクトが基になっています。つまり、これらは、データ バインディングの対象にすることができ、スタイルを設定できます。
次の例は、TextCell を使用して ListView 内の項目の外観を定義する方法を示しています。
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
次のスクリーンショットは、セルの外観の結果を示しています。
画像セル
ImageCell は、プライマリ テキストとセカンダリ テキストとともに画像を別々の行に表示します。 ImageCell は、TextCell からプロパティを継承し、セルに表示される画像を指定する ImageSource 型の ImageSource プロパティを定義します。 このプロパティは、BindableProperty オブジェクトが基になっています。つまり、データ バインディングの対象にすることができ、スタイルを設定できます。
次の例は ImageCell を使用して ListView の項目の外観を定義する方法を示しています。
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding Image}"
Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
次のスクリーンショットは、セルの外観の結果を示しています。
ビューのセル
ViewCell は、View によって外観が定義されるカスタム セルです。 ViewCell は、View 型の View プロパティを定義し、セルの内容を表すビューを定義します。 このプロパティは、BindableProperty オブジェクトが基になっています。つまり、データ バインディングの対象にすることができ、スタイルを設定できます。
次の例は、ViewCell を使用して ListView 内の項目の外観を定義する方法を示しています。
<ListView ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<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>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewCell 内では、レイアウトは任意の .NET MAUI レイアウトで管理できます。 この例では、レイアウトは Grid によって管理されます。 Grid には、Image オブジェクトと 2 つの Label オブジェクトが含まれており、これらはすべて Monkey
クラスのプロパティにバインドされています。
次のスクリーンショットは、リスト内の各項目をテンプレート化した結果を示しています。
実行時にアイテムの外観を選択
ListView 内の各項目の外観は、ItemTemplate
プロパティを DataTemplateSelector オブジェクトに設定することで、項目の値に基づいて実行時に選択できます。
<ContentPage ...
xmlns:templates="clr-namespace:ListViewDemos.Templates">
<ContentPage.Resources>
<DataTemplate x:Key="AmericanMonkeyTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="OtherMonkeyTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<templates:MonkeyDataTemplateSelector x:Key="MonkeySelector"
AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
</ContentPage.Resources>
<Grid Margin="20">
<ListView ItemsSource="{Binding Monkeys}"
ItemTemplate="{StaticResource MonkeySelector}" />
</Grid>
</ContentPage>
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 の作成」をご覧ください。
項目の選択に応答する
既定では、ListView の選択は有効になっています。 ただし、この動作は SelectionMode
プロパティを設定することにより変更できます。 ListViewSelectionMode
列挙型には、次のメンバーが定義されています。
None
- 項目が選択できないことを示します。Single
- 選択した項目が強調表示された状態で、1 つの項目を選択できることを示します。 これが既定値です。
ListView は、ユーザーがリストから項目を選択したことにより、またはアプリがプロパティを設定したことにより、SelectedItem
プロパティが変更されたときに発生する ItemSelected
イベントを定義します。 このイベントに付随する SelectedItemChangedEventArgs
オブジェクトには、SelectedItem
プロパティと SelectedItemIndex
プロパティがあります。
SelectionMode
プロパティが Single
に設定されている場合は、ListView の 1 つの項目を選択できます。 項目が選択されると、SelectedItem
プロパティは選択された項目の値に設定されます。 このプロパティが変更されると、ItemSelected
イベントが発生します。
次の例は、単一項目の選択に応答できる ListView を示しています。
<ListView ItemsSource="{Binding Monkeys}"
ItemSelected="OnItemSelected">
...
</ListView>
この例では、ItemSelected
イベントの発生時に OnItemSelected
イベント ハンドラーが実行され、イベント ハンドラーは選択された項目を取得します。
void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
Monkey item = args.SelectedItem as Monkey;
}
次のスクリーンショットは、ListView 内の 1 つの項目の選択を示しています。
選択のクリア
SelectedItem
プロパティは、プロパティまたはバインド先のオブジェクトを null
に設定することでクリアできます。
選択を無効にする
ListView の選択は既定で有効になっています。 ただし、SelectionMode
プロパティを None
に設定することで無効にできます。
<ListView ...
SelectionMode="None" />
SelectionMode
プロパティが None
に設定されている場合、ListView 内の項目は選択できず、SelectedItem
プロパティは null
のままになり、ItemSelected
イベントは発生しません。
キャッシュ データ
ListView はデータを表示するための強力なビューですが、いくつかの制限があります。 カスタム セルを使用する場合、特に深く入れ子になったビュー階層が含まれている場合や、複雑な測定を必要とする特定のレイアウトを使用する場合、スクロールのパフォーマンスが低下する場合があります。 ただし、パフォーマンス低下を回避するために使用できる手法があります。
ListView は、多くの場合、画面上に収まるよりもはるかに多くのデータを表示するために使用されます。 たとえば、音楽アプリには、何千ものエントリを含む曲のライブラリがある場合があります。 すべてのエントリに対して項目を作成すると、貴重なメモリが無駄になり、パフォーマンスが低下します。 行を常に作成して破棄するには、アプリでオブジェクトをインスタンス化してクリーンアップする必要があります。これにより、パフォーマンスも低下します。
メモリを節約するために、各プラットフォームのネイティブ ListView の同等物には、行を再利用するための組み込み機能があります。 画面に表示されるセルのみがメモリに読み込まれ、コンテンツが既存のセルに読み込まれます。 このパターンにより、アプリは何千ものオブジェクトをインスタンス化することがなくなり、時間とメモリが節約されます。
.NET MAUI では、次のメンバーを定義する ListViewCachingStrategy
列挙型によって ListView セルの再利用が許可されます。
RetainElement
は、ListView がリスト内の各項目のセルを生成することを指定します。RecycleElement
は、ListView が一覧のセルをリサイクルすることで、メモリ占有領域を最小化し、実行速度を短縮しようとします。RecycleElementAndDataTemplate
は、RecycleElement
と同様に、ListView が DataTemplateSelector を使用すると、DataTemplate オブジェクトがリスト内の項目の種類によってキャッシュされます。
要素を保持する
RetainElement
キャッシュ戦略では、ListView がリスト内の各項目のセルを生成することを指定し、これが既定の ListView 動作になります。 これは、次の状況で使用する必要があります。
- 各セルには、多数のバインド (20 ~ 30 以上) があります。
- セル テンプレートは頻繁に変更されます。
- テストでは、
RecycleElement
キャッシュ戦略によって実行速度が低下することが明らかになります。
カスタム セルを使用する場合は、RetainElement
キャッシュ戦略の結果を認識することが重要です。 セルの初期化コードは、セルの作成ごとに実行する必要があります。1 秒あたりに複数回実行できます。 この状況では、複数の入れ子になった Grid オブジェクトの使用など、ページ上で問題なかったレイアウト手法は、ユーザーがスクロールするときにリアルタイムで設定および破棄されるときにパフォーマンスのボトルネックになります。
要素のリサイクル
RecycleElement
キャッシング戦略では、ListView がメモリ占有領域と実行速度を最小限に抑えるためリストのセルをリサイクルするよう指定します。 このモードでは常にパフォーマンスが向上するとは限りません。テストを実行して改善点を特定する必要があります。 ただし、これは推奨される選択肢であり、次の状況で使用する必要があります。
- 各セルには、少数から中程度の数のバインドがあります。
- 各セルの
BindingContext
は、すべてのセル データを定義します。 - 各セルは大きく似ていますが、セル テンプレートは変更されません。
仮想化中、セルのバインド コンテキストは更新されるため、アプリでこのモードを使用する場合は、バインド コンテキストの更新が適切に処理されるようにする必要があります。 セルに関するすべてのデータは、バインディング コンテキストから取得する必要があります。または、整合性エラーが発生する可能性があります。 この問題は、データ バインディングを使用してセル データを表示することで回避できます。 または、次の例に示すように、カスタム セルのコンストラクターではなく、OnBindingContextChanged
オーバーライドでセル データを設定する必要があります。
public class CustomCell : ViewCell
{
Image image = null;
public CustomCell()
{
image = new Image();
View = image;
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var item = BindingContext as ImageItem;
if (item != null)
{
image.Source = item.ImageUrl;
}
}
}
DataTemplateSelector を使用して要素をリサイクルする
ListView が DataTemplateSelector を使用して DataTemplate を選択する場合、RecycleElement
キャッシュ戦略では DataTemplate オブジェクトはキャッシュされません。 代わりに、リスト内のデータの各項目に対して DataTemplate が選択されます。
Note
RecycleElement
キャッシュ戦略では、DataTemplateSelector が DataTemplate の選択を求められたら、それぞれの DataTemplate が同じ ViewCell 型を返す必要があります。 たとえば、MyDataTemplateA
(MyDataTemplateA
は MyViewCellA
型の ViewCell を返す) または MyDataTemplateB
(MyDataTemplateB
は MyViewCellB
型の ViewCell を返す) を返す DataTemplateSelector で ListView が指定された場合、MyDataTemplateA
が返されたときは MyViewCellA
を返す必要があり、そうでない場合は例外がスローされます。
DataTemplates を使用して要素をリサイクルする
RecycleElementAndDataTemplate
キャッシュ戦略は、RecycleElement
キャッシュ戦略に基づいています。さらに、ListView で DataTemplateSelector を使用して DataTemplate オブジェクトを選択するときに、リスト内の項目の種類によって DataTemplate オブジェクトがキャッシュされるようにします。 したがって、DataTemplate オブジェクトは項目インスタンスごとに 1 回ではなく、項目の種類ごとに 1 回選択されます。
Note
RecycleElementAndDataTemplate
キャッシュ戦略では、DataTemplateSelector によって返される DataTemplate オブジェクトは、Type
を受け取る DataTemplate コンストラクターを使用する必要があります。
キャッシュ戦略の設定
ListView キャッシュ戦略は、XAML で CachingStrategy
属性を設定することで定義できます。
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# では、キャッシュ戦略はコンストラクターのオーバーロードによって設定されます。
ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);
サブクラス化された ListView でキャッシュ戦略を設定する
サブクラス化された ListView で XAML から CachingStrategy
属性を設定しても、ListView に CachingStrategy
プロパティがないため、目的の動作は生成されません。 この問題の解決策は、ListViewCachingStrategy
パラメーターを受け取り、それを基本クラスに渡すサブクラス化された ListView でコンストラクターを指定することです。
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
次に、ListViewCachingStrategy
列挙値は、x:Arguments
属性を使用して XAML から指定できます。
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
ヘッダーとフッター
ListView では、リスト内の項目と共にスクロールするヘッダーとフッターを表示できます。 ヘッダーとフッターには、文字列、ビュー、DataTemplate オブジェクトを指定できます。
ListView は、ヘッダーとフッターを指定するための次のプロパティを定義します。
object
型のHeader
は、リストの先頭に表示される文字列、バインド、またはビューを指定します。- DataTemplate 型の
HeaderTemplate
は、Header
の書式を設定するために使用する DataTemplate を指定します。 object
型のFooter
は、リストの末尾に表示される文字列、バインド、またはビューを指定します。- DataTemplate 型の
FooterTemplate
は、Footer
の書式を設定するために使用する DataTemplate を指定します。
これらのプロパティはすべて、BindableProperty オブジェクトを基盤としています。つまり、プロパティをデータ バインディングの対象にすることができます。
ヘッダーとフッターに文字列を表示する
次の例に示すように、Header
プロパティと Footer
プロパティは、string
値に設定することもできます。
<ListView ItemsSource="{Binding Monkeys}"
Header="Monkeys"
Footer="2022">
...
</ListView>
次のスクリーンショットは、結果のヘッダーを示しています。
ヘッダーとフッターにビューを表示する
Header
プロパティと Footer
プロパティには、それぞれビューを設定できます。 1 つのビュー、または複数の子ビューを含むビューを指定できます。 次の例は、Header
プロパティと Footer
プロパティがそれぞれ、Label オブジェクトを含む Grid オブジェクトに設定されていることを示しています。
<ListView ItemsSource="{Binding Monkeys}">
<ListView.Header>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</ListView.Header>
<ListView.Footer>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</ListView.Footer>
...
</ListView>
次のスクリーンショットは、結果のヘッダーを示しています。
テンプレート化されたヘッダーとフッターを表示する
HeaderTemplate
プロパティと FooterTemplate
プロパティを DataTemplate オブジェクトに設定すると、ヘッダーとフッターの書式設定に使用できます。 このシナリオでは、以下の例に示すように、テンプレートを適用するためには、Header
プロパティと Footer
プロパティが現在のソースにバインドされている必要があります。
<ListView ItemsSource="{Binding Monkeys}"
Header="{Binding .}"
Footer="{Binding .}">
<ListView.HeaderTemplate>
<DataTemplate>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</ListView.FooterTemplate>
...
</ListView>
コントロール項目の区切り記号
既定では、iOS と Android では ListView 項目の間に区切り文字が表示されます。 この動作は、SeparatorVisibility
型の SeparatorVisibility
プロパティを None
に設定することで変更できます。
<ListView ...
SeparatorVisibility="None" />
さらに、区切り記号を有効にすると、その色は SeparatorColor
プロパティで設定できます。
<ListView ...
SeparatorColor="Blue" />
項目のサイズ設定
既定では、ListView 内のすべての項目は同じ高さになります。これは、各項目の外観を定義する DataTemplate の内容を基にしています。 ただし、この動作は、RowHeight
プロパティと HasUnevenRows
プロパティで変更できます。 既定では、HasUnevenRows
プロパティは false
です。
RowHeight
プロパティに int
の値を設定し、ListView の各アイテムの高さを表すことができます。これは、HasUnevenRows
が false
の場合に有効です。 HasUnevenRows
が true
に設定されている場合、ListView 内の各項目は異なる高さを設定できます。 各項目の高さは項目の DataTemplate の内容から導出されるため、各項目のサイズはその内容に合わせて調整されます。
HasUnevenRows
プロパティが true
である場合、DataTemplate 内の要素のレイアウト関連プロパティを変更することで、個々の ListView の項目のサイズを実行時にプログラムで変更できます。 次の例では、Image オブジェクトがタップされたときにその高さを変更します。
void OnImageTapped(object sender, EventArgs args)
{
Image image = sender as Image;
ViewCell viewCell = image.Parent.Parent as ViewCell;
if (image.HeightRequest < 250)
{
image.HeightRequest = image.Height + 100;
viewCell.ForceUpdateSize();
}
}
この例では、OnImageTapped
イベント ハンドラーは、Image オブジェクトがタップされたことに応答して実行されます。 イベント ハンドラーは Image の高さを更新し、Cell.ForceUpdateSize
メソッドは現在表示されていない場合でもセルのサイズを更新します。
警告
項目の動的なサイズ変更を過度に使用すると、ListView のパフォーマンスが低下する可能性があります。
右から左へのレイアウト
ListView を使用すると、FlowDirection
プロパティを RightToLeft
に設定することで、コンテンツを右から左へのフロー方向にレイアウトできます。 ただし、FlowDirection
プロパティは、ページまたはルート レイアウトに設定するのが理想的です。これにより、そのページまたはルート レイアウト内のすべての要素について、フローの方向が定まります。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListViewDemos.RightToLeftListPage"
Title="Right to left list"
FlowDirection="RightToLeft">
<Grid Margin="20">
<ListView ItemsSource="{Binding Monkeys}">
...
</ListView>
</Grid>
</ContentPage>
親を持つ要素の既定の FlowDirection
は MatchParent
です。 そのため、ListView は Grid から FlowDirection
プロパティ値を継承し、さらに ContentPage から FlowDirection
プロパティ値を継承します。
グループ化されたデータを表示する
大規模なデータ セットは、継続的にスクロールするリストで表示されると扱いにくくなることがよくあります。 このシナリオでは、データをグループにまとめることで、データ間の移動が容易になり、ユーザー エクスペリエンスが向上します。
データは、表示する前にグループ化する必要があります。 これは、各グループが項目のリストであるグループのリストを作成することによって実現できます。 グループのリストは IEnumerable<T>
コレクションである必要があり、T
では、次の 2 つのデータが定義されます。
- グループ名。
- グループに属する項目を定義する
IEnumerable
コレクション。
したがって、データをグループ化するプロセスは次のとおりです。
- 1 つの項目をモデル化する型を作成します。
- 1 つの項目グループをモデル化する型を作成します。
IEnumerable<T>
コレクションを作成します。T
は、項目の 1 つのグループをモデル化する型です。 このコレクションは、グループ化されたデータを格納するグループのコレクションです。IEnumerable<T>
コレクションにデータを追加します。
例
データをグループ化する場合、最初の手順は、1 つの項目をモデル化する型を作成することです。 次の例は、Animal
クラスを示しています。
public class Animal
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
Animal
クラスは、1 つの項目をモデル化します。 その後、項目のグループをモデル化する型を作成できます。 次の例は、AnimalGroup
クラスを示しています。
public class AnimalGroup : List<Animal>
{
public string Name { get; private set; }
public AnimalGroup(string name, List<Animal> animals) : base(animals)
{
Name = name;
}
}
AnimalGroup
クラスは List<T>
クラスを継承し、グループ名を表す Name
プロパティを追加します。
その後、グループの IEnumerable<T>
コレクションを作成できます。
public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();
このコードでは、コレクション内の各項目が AnimalGroup
オブジェクトである、Animals
という名前のコレクションを定義します。 各 AnimalGroup
オブジェクトは、名前と、グループ内の Animal
オブジェクトを定義する List<Animal>
コレクションで構成されます。
その後、グループ化されたデータを Animals
コレクションに追加できます。
Animals.Add(new AnimalGroup("Bears", new List<Animal>
{
new Animal
{
Name = "American Black Bear",
Location = "North America",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
},
new Animal
{
Name = "Asian Black Bear",
Location = "Asia",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
},
// ...
}));
Animals.Add(new AnimalGroup("Monkeys", new List<Animal>
{
new Animal
{
Name = "Baboon",
Location = "Africa & Asia",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
},
new Animal
{
Name = "Capuchin Monkey",
Location = "Central & South America",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
},
new Animal
{
Name = "Blue Monkey",
Location = "Central and East Africa",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
},
// ...
}));
このコードは、Animals
コレクション内に 2 つのグループを作成します。 1 つ目の AnimalGroup
は Bears
という名前が付けられ、クマの詳細の List<Animal>
コレクションが含まれています。 2 つ目 AnimalGroup
は Monkeys
という名前が付けられ、サルの詳細の List<Animal>
コレクションが含まれています。
ListView は、IsGroupingEnabled
プロパティを true
に設定することで、データが正しくグループ化されていれば、グループ化されたデータを表示します。
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<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>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
同等の C# コードを次に示します。
ListView listView = new ListView
{
IsGroupingEnabled = true
};
listView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
// ...
ListView 内の各項目の外観は、ItemTemplate
プロパティを DataTemplate に設定することで定義されます。 詳細については、「項目の外観を定義する」をご覧ください。
次のスクリーンショットは、グループ化されたデータを表示する ListView を示しています。
Note
既定では、ListView によりグループ ヘッダーにグループ名が表示されます。 この動作は、グループ ヘッダーをカスタマイズすることで変更できます。
グループ ヘッダーをカスタマイズする
各グループ ヘッダーの外観は、ListView.GroupHeaderTemplate
プロパティを DataTemplate に設定することでカスタマイズできます。
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="True">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"
BackgroundColor="LightGray"
FontSize="18"
FontAttributes="Bold" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
...
</ListView>
この例では、各グループ ヘッダーは、グループ名を表示する Label に設定されており、その他の外観プロパティが設定されています。 次のスクリーンショットは、カスタマイズされたグループ ヘッダーを示しています。
重要
GroupHeaderTemplate
プロパティと GroupDisplayBinding
プロパティは、同時には有効にできません。 そのため、両方のプロパティを設定しないでください。
テンプレートのないグループ
ListView は、ItemTemplate
プロパティを DataTemplate に設定しなくても、正しくグループ化されたデータを表示できます。
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="true" />
このシナリオでは、1 つの項目をモデル化する型と、1 つの項目グループをモデル化する型の ToString
メソッドを上書きすることで、意味のあるデータを表示できます。
スクロールの制御
ListView は、項目をスクロールして表示する 2 つの ScrollTo
メソッドを定義します。 オーバーロードの 1 つは指定された項目をスクロールして表示し、もう 1 つのオーバーロードは指定されたグループ内の指定された項目をスクロールして表示します。 どちらのオーバーロードにも追加の引数があり、スクロール完了後の項目の正確な位置を指定したり、スクロールをアニメーション化するかどうかを指定したりできます。
ListView は、ScrollTo
メソッドのいずれかが呼び出されたときに発生する ScrollToRequested
イベントを定義します。 ScrollToRequested
イベントに付随する ScrollToRequestedEventArgs
オブジェクトには、ShouldAnimate
、Element、Mode
、Position
などの多くのプロパティがあります。 これらのプロパティの一部は、ScrollTo
メソッド呼び出しで指定された引数から設定されます。
さらに、ListView は、スクロールが発生したことを示すために発生する Scrolled
イベントを定義します。 Scrolled
イベントに付随する ScrolledEventArgs
オブジェクトには、ScrollX
プロパティと ScrollY
プロパティがあります。
スクロールの検出
ListView は、スクロールが発生したことを示すために発生する Scrolled
イベントを定義します。 Scrolled
イベントに付随するオブジェクトを表す ItemsViewScrolledEventArgs
クラスは、次のプロパティを定義します。
double
型のScrollX
は、スクロールの X 位置を表します。double
型のScrollY
は、スクロールの Y 位置を表します。
次の XAML の例は、Scrolled
イベントのイベント ハンドラーを設定する ListView を示しています。
<ListView Scrolled="OnListViewScrolled">
...
</ListView>
同等の C# コードを次に示します。
ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;
このコード例では、Scrolled
イベントが発生すると、OnListViewScrolled
イベント ハンドラーが実行されます。
void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
// Custom logic
}
重要
Scrolled
イベントは 、ユーザーが開始したスクロールとプログラムによるスクロールに対して発生します。
項目をスクロールして表示する
ScrollTo
メソッドは、指定された項目をスクロールして表示します。 listView
という名前の ListView オブジェクトがある場合、次の例はテングザル項目をスクロールして表示する方法を示しています。
MonkeysViewModel viewModel = BindingContext as MonkeysViewModel;
Monkey monkey = viewModel.Monkeys.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, ScrollToPosition.MakeVisible, true);
または、グループ化されたデータの項目を、項目とグループを指定してスクロール表示することもできます。 次の例は、Monkeys グループの Proboscis Monkey 項目をスクロールして表示する方法を示しています:
GroupedAnimalsViewModel viewModel = BindingContext as GroupedAnimalsViewModel;
AnimalGroup group = viewModel.Animals.FirstOrDefault(a => a.Name == "Monkeys");
Animal monkey = group.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, group, ScrollToPosition.MakeVisible, true);
Note
ScrollToRequested
イベントは、 ScrollTo
メソッドが呼び出されたときに発生します。
スクロール アニメーションの無効化
項目をスクロールして表示すると、スクロール アニメーションが表示されます。 ただし、ScrollTo
メソッドの animated
引数を false
に設定することで、このアニメーションを無効にすることができます。
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: false);
スクロール位置の制御
項目をスクロールして表示する場合、スクロールが完了した後の項目の正確な位置は、ScrollTo
メソッドの position
引数を使用して指定できます。 この引数は ScrollToPosition
列挙メンバーを受け入れます。
MakeVisible
ScrollToPosition.MakeVisible
メンバーは、ビューに表示されるまで項目をスクロールする必要があることを示します。
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: true);
スタート
ScrollToPosition.Start
メンバーは、項目をビューの先頭までスクロールする必要があることを示します。
listView.ScrollTo(monkey, position: ScrollToPosition.Start, animate: true);
中央
ScrollToPosition.Center
メンバーは、項目をビューの中央までスクロールする必要があることを示します。
listView.ScrollTo(monkey, position: ScrollToPosition.Center, animate: true);
末尾
ScrollToPosition.End
メンバーは、項目をビューの末尾までスクロールする必要があることを示します。
listView.ScrollTo(monkey, position: ScrollToPosition.End, animate: true);
スクロール バーの表示
ListView は、バインド可能なプロパティによってサポートされる HorizontalScrollBarVisibility
および VerticalScrollBarVisibility
プロパティを定義します。 これらのプロパティは、水平スクロール バーまたは垂直スクロール バーが表示されるタイミングを表す ScrollBarVisibility
列挙値を取得または設定します。 ScrollBarVisibility
列挙型には、次のメンバーが定義されています。
Default
は、プラットフォームの既定のスクロール バーの動作を示し、VerticalScrollBarVisibility
およびHorizontalScrollBarVisibility
プロパティの既定値です。Always
は、コンテンツがビューに収まる場合でも、スクロール バーが表示されることを示します。Never
は、コンテンツがビューに収まらない場合でも、スクロール バーが表示されないことを示します。
コンテキスト メニューの追加
ListView は、コンテキスト メニュー項目をサポートします。これは、各項目の DataTemplate 内の ViewCell.ContextActions
コレクションに追加される MenuItem オブジェクトとして定義されます。
<ListView x:Name="listView"
ItemsSource="{Binding Monkeys}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Favorite"
Command="{Binding Source={x:Reference listView}, Path=BindingContext.FavoriteCommand}"
CommandParameter="{Binding}" />
<MenuItem Text="Delete"
Command="{Binding Source={x:Reference listView}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}" />
</ViewCell.ContextActions>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListView 内の項目を右クリックすると、MenuItem オブジェクトが表示されます。
メニュー項目の詳細については、「メニュー項目の表示」を参照してください。
引っ張って更新
ListView は、引っ張って更新する機能をサポートしています。これにより、項目のリストをプルダウンすることで、表示されているデータを更新できます。
引っ張って更新する機能を有効にするには、IsPullToRefreshEnabled
プロパティを true
に設定します。 更新がトリガーされると、ListView によって Refreshing
イベントが発生し、IsRefreshing
プロパティが true
に設定されます。 ListView のコンテンツを更新するために必要なコードは、Refreshing
イベントのハンドラーによって実行されるか、RefreshCommand
が実行する ICommand 実装によって実行される必要があります。 ListView が更新されたら、IsRefreshing
プロパティを false
に設定するか、ListView で EndRefresh
メソッドを呼び出して、更新が完了したことを示す必要があります。
次の例は、引っ張って更新する機能を使用する ListView を示しています。
<ListView ItemsSource="{Binding Animals}"
IsPullToRefreshEnabled="true"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
この例では、ユーザーが更新を開始すると、RefreshCommand
プロパティによって定義された ICommand が実行され、表示されている項目が更新されます。 更新の実行中に、アニメーション化された進行状況が、円で構成される更新のビジュアライゼーションで表示されます。 IsRefreshing
プロパティの値は、更新操作の現在の状態を示します。 更新がトリガーされると、このプロパティは自動的に true
に移行します。 更新が完了したら、プロパティを false
にリセットする必要があります。
.NET MAUI