This article has been localized into French by the community.
Le contrôle ItemsControl
WPF dispose d'une large variété de contrôles pour afficher une liste de données. Ces contrôles se présentent sous plusieurs formes et varient selon leur complexité et les taches qu'ils peuvent accomplir pour vous. La variante la plus simple est le ItemsControl qui n'est plus ou moins qu'un simple affichage en séquence des éléments sur lequel il est possible d'appliquer des styles et des modèles, ce qui est largement suffisant dans la plupart des cas.
Un exemple simple du contrôle ItemsControl
Démarrons immédiatement avec un exemple tout simple, où nous remplissons manuellement le ItemsControl avec une liste d’éléments. Nous verrons ainsi que le ItemsControl est très facile à utiliser :
<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="ItemsControlSample" Height="150" Width="200">
<Grid Margin="10">
<ItemsControl>
<system:String>ItemsControl Item #1</system:String>
<system:String>ItemsControl Item #2</system:String>
<system:String>ItemsControl Item #3</system:String>
<system:String>ItemsControl Item #4</system:String>
<system:String>ItemsControl Item #5</system:String>
</ItemsControl>
</Grid>
</Window>
Comme vous pouvez le voir, rien ne nous indique que nous utilisons un contrôle pour répéter les éléments et que nous n'avons pas créé manuellement 5 contrôles TextBlock pour afficher ces éléments - par défaut le contrôle ItemsControl ne possède aucun visuel particulier. Si l'on clique sur l'un des éléments, rien ne se produit, parce qu'il n'y a aucun concept d'élément(s) sélectionné(s), ni de fonctionnalité de ce genre.
ItemsControl avec liaison de données (data binding)
Bien évidemment, les ItemsControl n'ont pas vocation à être utilisés avec des éléments que l'on définit directement dans le balisage XAML comme nous l'avons fait dans le premier exemple. Comme la plupart des autres contrôles en WPF, le ItemsControl est en effet conçu pour utiliser la liaison de données (data binding), dans laquelle nous utilisons un modèle (template) pour définir la façon dont les classes du Code-behind devront être présentées à l'utilisateur.
Afin de démontrer cela, j'ai préparé un exemple dans lequel nous affichons une liste de choses à faire (TODO list), et afin de vous montrer la flexibilité offerte par la création de vos propres modèles, j'ai utilisé un contrôle de barre de progression (ProgressBar) pour afficher le pourcentage de réalisation. On commence par un peu de code, ensuite une copie d'écran et enfin les explications :
<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlDataBindingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ItemsControlDataBindingSample" Height="150" Width="300">
<Grid Margin="10">
<ItemsControl Name="icTodoList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}" />
<ProgressBar Grid.Column="1" Minimum="0" Maximum="100" Value="{Binding Completion}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
using System;
using System.Windows;
using System.Collections.Generic;
namespace WpfTutorialSamples.ItemsControl
{
public partial class ItemsControlDataBindingSample : Window
{
public ItemsControlDataBindingSample()
{
InitializeComponent();
List<TodoItem> items = new List<TodoItem>();
items.Add(new TodoItem() { Title = "Complete this WPF tutorial", Completion = 45 });
items.Add(new TodoItem() { Title = "Learn C#", Completion = 80 });
items.Add(new TodoItem() { Title = "Wash the car", Completion = 0 });
icTodoList.ItemsSource = items;
}
}
public class TodoItem
{
public string Title { get; set; }
public int Completion { get; set; }
}
}
La partie la plus importante de cet exemple est le modèle (template) que nous avons spécifié directement à l'intérieur du ItemsControl, en utilisant une balise DataTemplate à l'intérieur de la balise ItemsControl.ItemTemplate. Nous avons ajouté un Grid Panel pour afficher 2 colonnes : dans la première nous avons un TextBloc qui affiche le titre de la tache à faire (TodoItem.Title), et dans la deuxième colonne, nous avons le contrôle ProgressBar qui est lié à la propriété Completion.
Le modèle (template) représente donc un TodoItem qui est défini dans le Code-behind. Dans le Code-behind, nous allons également instancier plusieurs objets TodoItem et les ajouter à une liste. Cette liste est ensuite assignée à la propriété ItemsSource de notre ItemsControl, ce qui fera le reste du travail à notre place. Chaque élément de la liste est affiché en utilisant notre modèle, comme on peut le voir dans la copie d'écran qui résulte de l'exécution de notre exemple.
La propriété ItemsPanelTemplate
Dans les exemples ci-dessus, tous les éléments sont affichés du haut vers le bas, et chaque élément remplit la totalité de la ligne. Il en est ainsi parce que le ItemsControl utilise par défaut un StackPanel aligné verticalement pour afficher les éléments. Il est cependant très facile de changer cela, puisque le ItemsControl nous autorise à changer le type de panel utilisé pour contenir les éléments. En voici un exemple :
<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlPanelSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="ItemsControlPanelSample" Height="150" Width="250">
<Grid Margin="10">
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Margin="0,0,5,5" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<system:String>Item #1</system:String>
<system:String>Item #2</system:String>
<system:String>Item #3</system:String>
<system:String>Item #4</system:String>
<system:String>Item #5</system:String>
</ItemsControl>
</Grid>
</Window>
Nous avons spécifié que le ItemsControl devait utiliser un WrapPanel en tant que modèle (template) car nous avons déclaré un WrapPanel dans la propriété ItemsPanelTemplate, et juste pour le fun, nous avons rajouté un ItemTemplate afin que les éléments de la liste soient affichés sous forme de boutons. Il est possible d'utiliser n'importe quel panel de WPF, mais certains sont plus utiles que d'autres.
Un autre bon exemple est l'utilisation de l'UniformGrid panel : en définissant uniquement le nombre de colonnes, ce panel nous permet d'avoir nos éléments soigneusement affichés dans des colonnes de largeurs identiques :
<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlPanelSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="ItemsControlPanelSample" Height="150" Width="250">
<Grid Margin="10">
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Margin="0,0,5,5" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<system:String>Item #1</system:String>
<system:String>Item #2</system:String>
<system:String>Item #3</system:String>
<system:String>Item #4</system:String>
<system:String>Item #5</system:String>
</ItemsControl>
</Grid>
</Window>
ItemsControl avec des barres de défilement (scrollbars)
Une fois que vous aurez appris à utiliser le ItemsControl, il se peut que vous rencontriez un problème très classique : par défaut, le ItemsControl ne possède pas de barres de défilement (scrollbars), ce qui signifie que si le contenu n'est pas adapté, il sera tronqué. On peut se rendre compte de cela en reprenant le premier exemple de cet article et en rapetissant la fenêtre.
WPF nous permet cependant de régler ce problème très facilement. Il existe de nombreuses solutions, et il est par exemple possible de modifier le modèle (template) utilisé par ItemsControl afin d'inclure un contrôle ScrollViewer, mais la solution la plus facile reste d'insérer un ScrollViewer autour de ItemsControl. En voici un exemple :
<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="ItemsControlSample" Height="150" Width="200">
<Grid Margin="10">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ItemsControl>
<system:String>ItemsControl Item #1</system:String>
<system:String>ItemsControl Item #2</system:String>
<system:String>ItemsControl Item #3</system:String>
<system:String>ItemsControl Item #4</system:String>
<system:String>ItemsControl Item #5</system:String>
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>
Dans cet exemple, nous avons réglé les options de visibilité des 2 barres de défilement sur Auto afin de ne les afficher qu'en cas de nécessité. Comme on peut le voir sur la copie d'écran, il est maintenant possible de scroller la totalité de la liste des éléments.
Résumé
Le ItemsControl est idéal lorsque l'on veut un contrôle total sur la façon d'afficher les données et lorsque l'on n'a pas besoin de sélectionner des éléments de la liste. Cependant, si vous souhaitez que l'utilisateur puisse sélectionner des éléments de la liste, il est préférable d'utiliser d'autres contrôles, tels que la ListBox ou les ListView qui seront étudiés en détail dans les prochains chapitres.