- UWP
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 !
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.
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
:
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>
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:
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é !