次の方法で共有


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 プロパティは、同時には有効にできません。 そのため、このプロパティを設定すると、GroupDisplayBindingnull に設定されます。
  • 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 は、HasUnevenRowsfalse の場合に各行の高さを決定します。
  • object 型の SelectedItem は、ListView で現在選択されている項目を表します。
  • ListViewSelectionMode 型の SelectionMode は、ListView で項目を選択できるかどうかを示します。 このプロパティの既定値は Single です。
  • Color 型の SeparatorColor は、リスト内の項目を区切るバーの色を定義します。
  • SeparatorVisibility 型の SeparatorVisibility は、項目間で区切り記号を表示するかどうかを定義します。
  • ScrollBarVisibility 型の VerticalScrollBarVisibility は、垂直スクロール バーが表示されるタイミングを示します。

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

さらに、ListView は、BindableProperty オブジェクトによってサポートされていない次のプロパティを定義します。

  • BindingBase 型の GroupDisplayBinding は、グループ ヘッダーの表示に使用するバインディングです。 このプロパティと GroupHeaderTemplate プロパティは、同時には有効にできません。 そのため、このプロパティを設定すると、GroupHeaderTemplatenull に設定されます。
  • 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 のスクリーンショット。

データ テンプレートの詳細については、「データ テンプレート」をご覧ください。

セル

ListView 内の各項目の外観は DataTemplate によって定義され、DataTemplate は項目を表示するために Cell クラスを参照する必要があります。 各セルは、ListView 内のデータ項目を表します。 .NET MAUI には、次の組み込みセルが含まれています。

  • TextCell は、プライマリ テキストとセカンダリ テキストを別々の行に表示します。
  • ImageCell は、プライマリ テキストとセカンダリ テキストとともに画像を別々の行に表示します。
  • SwitchCell は、テキストと、オンまたはオフに切り替えることができるスイッチを表示します。
  • EntryCell は、編集可能なラベルとテキストを表示します。
  • ViewCell は、外観が View で定義されているカスタム セルです。 このセル タイプは、ListView 内の各項目の外観を完全に定義する場合に使用する必要があります。

通常、SwitchCellEntryCellTableView でのみ使用され、ListView では使用されません。 SwitchCellEntryCell の詳細については、「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>

次のスクリーンショットは、セルの外観の結果を示しています。

各項目が TextCell である 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>

次のスクリーンショットは、セルの外観の結果を示しています。

各項目が ImageCell である ListView のスクリーンショット。

ビューのセル

ViewCell は、View によって外観が定義されるカスタム セルです。 ViewCell は、View 型の View プロパティを定義し、セルの内容を表すビューを定義します。 このプロパティは、BindableProperty オブジェクトが基になっています。つまり、データ バインディングの対象にすることができ、スタイルを設定できます。

Note

View プロパティは ViewCell クラスのコンテンツ プロパティであるため、XAML から明示的に設定する必要はありません。

次の例は、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 クラスのプロパティにバインドされています。

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

各項目が ViewCell でテンプレート化されている ListView のスクリーンショット。

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

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 テンプレートを返し、サルの名前と場所が銀色で表示されます。

ListView のランタイム項目テンプレートの選択のスクリーンショット。

データ テンプレート セレクターの詳細については、「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 つの項目の選択を示しています。

1 つが選択された ListView のスクリーンショット。

選択のクリア

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 と同様に、ListViewDataTemplateSelector を使用すると、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 を使用して要素をリサイクルする

ListViewDataTemplateSelector を使用して DataTemplate を選択する場合、RecycleElement キャッシュ戦略では DataTemplate オブジェクトはキャッシュされません。 代わりに、リスト内のデータの各項目に対して DataTemplate が選択されます。

Note

RecycleElement キャッシュ戦略では、DataTemplateSelectorDataTemplate の選択を求められたら、それぞれの DataTemplate が同じ ViewCell 型を返す必要があります。 たとえば、MyDataTemplateA (MyDataTemplateAMyViewCellA 型の ViewCell を返す) または MyDataTemplateB (MyDataTemplateBMyViewCellB 型の ViewCell を返す) を返す DataTemplateSelectorListView が指定された場合、MyDataTemplateA が返されたときは MyViewCellA を返す必要があり、そうでない場合は例外がスローされます。

DataTemplates を使用して要素をリサイクルする

RecycleElementAndDataTemplate キャッシュ戦略は、RecycleElement キャッシュ戦略に基づいています。さらに、ListViewDataTemplateSelector を使用して 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 属性を設定しても、ListViewCachingStrategy プロパティがないため、目的の動作は生成されません。 この問題の解決策は、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>

次のスクリーンショットは、結果のヘッダーを示しています。

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>

次のスクリーンショットは、結果のヘッダーを示しています。

ビューを使用した CollectionView のヘッダーとフッターのスクリーンショット。

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 の各アイテムの高さを表すことができます。これは、HasUnevenRowsfalse の場合に有効です。 HasUnevenRowstrue に設定されている場合、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>

親を持つ要素の既定の FlowDirectionMatchParent です。 そのため、ListViewGrid から 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 つ目の AnimalGroupBears という名前が付けられ、クマの詳細の List<Animal> コレクションが含まれています。 2 つ目 AnimalGroupMonkeys という名前が付けられ、サルの詳細の 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 を示しています。

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 に設定されており、その他の外観プロパティが設定されています。 次のスクリーンショットは、カスタマイズされたグループ ヘッダーを示しています。

ListView のカスタマイズされたグループ ヘッダーのスクリーンショット。

重要

GroupHeaderTemplate プロパティと GroupDisplayBinding プロパティは、同時には有効にできません。 そのため、両方のプロパティを設定しないでください。

テンプレートのないグループ

ListView は、ItemTemplate プロパティを DataTemplate に設定しなくても、正しくグループ化されたデータを表示できます。

<ListView ItemsSource="{Binding Animals}"
          IsGroupingEnabled="true" />

このシナリオでは、1 つの項目をモデル化する型と、1 つの項目グループをモデル化する型の ToString メソッドを上書きすることで、意味のあるデータを表示できます。

スクロールの制御

ListView は、項目をスクロールして表示する 2 つの ScrollTo メソッドを定義します。 オーバーロードの 1 つは指定された項目をスクロールして表示し、もう 1 つのオーバーロードは指定されたグループ内の指定された項目をスクロールして表示します。 どちらのオーバーロードにも追加の引数があり、スクロール完了後の項目の正確な位置を指定したり、スクロールをアニメーション化するかどうかを指定したりできます。

ListView は、ScrollTo メソッドのいずれかが呼び出されたときに発生する ScrollToRequested イベントを定義します。 ScrollToRequested イベントに付随する ScrollToRequestedEventArgs オブジェクトには、ShouldAnimateElementModePosition などの多くのプロパティがあります。 これらのプロパティの一部は、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 オブジェクトが表示されます。

CollectionView のコンテキスト メニュー項目のスクリーンショット。

メニュー項目の詳細については、「メニュー項目の表示」を参照してください。

引っ張って更新

ListView は、引っ張って更新する機能をサポートしています。これにより、項目のリストをプルダウンすることで、表示されているデータを更新できます。

引っ張って更新する機能を有効にするには、IsPullToRefreshEnabled プロパティを true に設定します。 更新がトリガーされると、ListView によって Refreshing イベントが発生し、IsRefreshing プロパティが true に設定されます。 ListView のコンテンツを更新するために必要なコードは、Refreshing イベントのハンドラーによって実行されるか、RefreshCommand が実行する ICommand 実装によって実行される必要があります。 ListView が更新されたら、IsRefreshing プロパティを false に設定するか、ListViewEndRefresh メソッドを呼び出して、更新が完了したことを示す必要があります。

次の例は、引っ張って更新する機能を使用する 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 にリセットする必要があります。