Photo par pxhere.com

Comment afficher une liste groupée dans UWP

Dans ce tutoriel, nous verrons comment regrouper les éléments et personnaliser facilement le style de notre liste groupée.

Posted by Damien Aicheh on July 23, 2018 · 8 mins

Après de nombreuses recherches sur mes moteurs de recherche favoris, je n’ai pas réussi à trouver un tutoriel complet pour regrouper les éléments d’une liste et personnaliser les en-têtes d’une ListView. J’ai donc décidé de créer ce tutoriel ; à la fin de celui-ci vous pouvez télécharger le code source complet et jouer avec :)

Pour ce poste, nous afficherons les membres de l’équipe de France de football qui viennent de remporter la Coupe du Monde !

Préparer les données

Dans un PlayerViewModel nous avons la liste des joueurs, et nous devons la filtrer en fonction de leur poste sur le terrain, pour créer un groupe de joueurs. Pour ce faire, nous avons défini une classe enum appelée Position.

private ObservableCollection<GroupInfosList> _players = new ObservableCollection<GroupInfosList>();
public ObservableCollection<GroupInfosList> Players
{
    get => _players;
    set => value = _players;
}
        
public void GeneratePanierByStatusGroup(List<Player> players)
{
    var query = from item in players
                group item by item.Position into g
                orderby g.Key
                select new { GroupName = g.Key, Items = g };

    foreach (var g in query)
    {
        GroupInfosList info = new GroupInfosList();
        info.Key = g.GroupName + " (" + g.Items.Count() + ")" ;

        foreach (var item in g.Items)
        {
            info.Add(item);
        }

        Players.Add(info);
    }
}

Dans le code ci-dessus, nous utilisons une query pour trier nos joueurs en fonction de leur position sur le terrain. Ensuite, nous pouvons ajouter tous les groupes de joueurs dans notre ObservableCollection avec un nom de groupe personnalisé défini par info.Key. Comme vous pouvez le voir, nous affichons le poste du joueur et le nombre de joueurs dans ce groupe.

Gérer la vue

Afficher la liste des joueurs

Maintenant, nous pouvons designer la liste en xaml avec le composant ListView:

<ListView ItemsSource="{Binding Source={StaticResource PlayerSource}}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem" BasedOn="{StaticResource ListViewItemExpanded}">
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>            
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="models:Player">                    
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition Width="50" />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{x:Bind FullName}" Style="{StaticResource TextStyle}" />
                <TextBlock Grid.Column="1" Text="{x:Bind Number}"
                           Style="{StaticResource NumberTextStyle}" />
            </Grid>                    
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Key}" Margin="10,0"
                               Foreground="Black" FontWeight="Bold" />
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ListView.GroupStyle>
</ListView>

Le point clé ici est la balise GroupStyle.HeaderTemplate: elle nous donne la possibilité d’afficher le titre de chaque groupe que nous avons précédemment défini par la variable info.key.

Pour lier une liste d’éléments groupés à notre ListView, nous devons utiliser une CollectionViewSource:

<Page.Resources>
    <CollectionViewSource x:Name="PlayerSource" Source="{Binding Players}" IsSourceGrouped="true" />
</Page.Resources>

The CollectionViewSource is the key thing. It has our players grouped list as a Source and it’s used like a StaticResource in the ItemsSource property of our ListView.

En faisant cela, vous obtiendrez le design par défaut d’un élément groupé ListView:

Default design

Ajouter du design

Personnalisez l’en-tête de groupe

Notre liste est un peu triste, donnons-lui des couleurs !

Pour pouvoir redesigner les en-têtes de groupe, nous devons redéfinir la balise GroupStyle.HeaderContainerStyle. Pour ce faire, je vous recommande de copier & coller le template ListViewHeaderItem par défaut de la classe generic.xaml et de jouer avec.


Si vous ne savez pas comment l’obtenir, appuyez simplement sur F12 sur votre clavier ou faites un clic droit et choisissez Aller à la définition sur un   ThemeResource officiel, par exemple le Background par défaut d’une nouvelle page générée :

Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"

Vous serez automatiquement redirigé vers le fichier generic.xaml.


In the code below, we define our group Header (Background, Margin…) So we have full control on it.

<GroupStyle.HeaderContainerStyle>
    <Style TargetType="ListViewHeaderItem">
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
        <Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}" />
        <Setter Property="Background" Value="#2045aa" />
        <Setter Property="Margin" Value="0" />
        <Setter Property="Padding" Value="12,8,12,0" />
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="MinHeight" Value="{ThemeResource ListViewHeaderItemMinHeight}" />
        <Setter Property="UseSystemFocusVisuals" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListViewHeaderItem">
                    <ContentPresenter x:Name="ContentPresenter"
                                Background="{TemplateBinding Background}"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                ContentTransitions="{TemplateBinding ContentTransitions}"
                                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</GroupStyle.HeaderContainerStyle>

Ajouter un en-tête à notre liste

Enfin, ajoutons un en-tête en haut de notre liste de joueurs. C’est très simple, nous ajoutons simplement le contenu dans la balise ListView.HeaderTemplate:

<ListView.HeaderTemplate>
    <DataTemplate>
        <Grid Background="#0c2569" Height="70">
            <TextBlock Text="French Team | World Cup 2018" FontWeight="Bold"
                       HorizontalAlignment="Center" VerticalAlignment="Center"
                       FontSize="20" Foreground="White" />
        </Grid>
    </DataTemplate>
</ListView.HeaderTemplate>

Voici notre résultat final:

Final result

Vous trouverez un exemple de code sur ce répertoire Github.

Happy codding !

Vous avez aimé ce tutoriel ? Laissez une étoile sur le répertoire Github associé !

N'hésitez pas à me suivre sur pour ne pas rater mon prochain tutoriel !