shuhelohelo’s blog

Xamarin.Forms多めです.

Xamarin.FormsのCollectionViewでグルーピング表示する

docs.microsoft.com

リスト表示するときに,何かしらの項目でグループ化して表示したいときがあります.

例えば,年代であったり,名字であったり,好きなゲームのジャンルであったり,動物の種類であったりといった具合です.

CollectionViewにはデータをグルーピングして表示する機能がある,と言いたいところなのですが,あるといえばある,,,という感じです.

いつもどおりListやObservableCollectionなどをバインディングすればあとはちょこちょこ指定すればいい感じにグルーピングして表示してくれるかと思いきや,データのグルーピングは自分でやって,それをバインディングする必要があります.

例えば以下のようなPersonクラスのコレクションがあったとしましょう.(JsonPropertyName属性は無視してください)

    //こんなクラスの
    public class Person
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }
        [JsonPropertyName("first_name")]
        public string FirstName { get; set; }
        [JsonPropertyName("last_name")]
        public string LastName { get; set; }
        [JsonPropertyName("email")]
        public string Email { get; set; }
        [JsonPropertyName("gender")]
        public string Gender { get; set; }
        [JsonPropertyName("ip_address")]
        public string IpAddress { get; set; }
    }
    //こんなコレクション
        public List<Person> People { get; set; }

ここからグループ化されたデータを作ります.

今回はLastNameプロパティでグループ化します.

まずはグループごとのコレクションを保持するクラスを用意します.

    public class PeopleGroup : List<Person>
    {
        //グループのヘッダに表示するために使う.
        public string LastName { get; private set; }

        public PeopleGroup(string lastName, List<Person> people) : base(people)
        {
            this.LastName = lastName;
        }
    }

そしてこのグループのコレクションをCollectionViewとバインドします.最終的に.

そして,Xaml側は以下のとおりです.

    <CollectionView
        IsGrouped="True"
        ItemsSource="{Binding GroupedPeople}"
        VerticalOptions="CenterAndExpand">
        <CollectionView.ItemsLayout>
            <LinearItemsLayout Orientation="Vertical" />
        </CollectionView.ItemsLayout>
        <CollectionView.GroupHeaderTemplate>
            <DataTemplate>
                <Grid>
                    <Frame Margin="10" BackgroundColor="LightBlue">
                        <Label FontSize="Large" Text="{Binding LastName}" />
                    </Frame>
                </Grid>
            </DataTemplate>
        </CollectionView.GroupHeaderTemplate>
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Frame BorderColor="Gray" CornerRadius="0">
                    <StackLayout>
                        <Label Text="{Binding LastName}" />
                        <Label Text="{Binding FirstName}" />
                    </StackLayout>
                </Frame>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

Xaml側のポイントは2つ

  • IsGroupedTrueにする.
  • GroupHeaderTemplateを定義する

です.

他にもGroupFooterTemplateもあるので,必要であればそちらも定義できます.

実行すると,以下のようにLastNameでグループ化されて表示されます.

f:id:shuhelohelo:20200625221511p:plain

ソースコード

github.com