TOC

This article has been localized into French by the community.

Les contrôles de listes:

Le contrôle ListBox

Dans le dernier article, nous avons vu brièvement les ItemsControl, qui sont probablement les listes les plus simples à utiliser avec WPF. Le ListBox est le prochain élément que nous allons étudier, et ajoute quelques fonctionnalités supplémentaires. Une des différences majeures est le fait que le contrôle ListBox gère en fait les sélections, permettant à l'utilisateur final de sélectionner un ou plusieurs objets depuis la liste et en ayant automatiquement un rendu visuel de sa sélection.

Ci-dessous un exemple très simple d'un contrôle ListBox

<Window x:Class="WpfTutorialSamples.ListBox_control.ListBoxSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBoxSample" Height="120" Width="200">
    <Grid Margin="10">
		<ListBox>
			<ListBoxItem>ListBox Item #1</ListBoxItem>
			<ListBoxItem>ListBox Item #2</ListBoxItem>
			<ListBoxItem>ListBox Item #3</ListBoxItem>
		</ListBox>
	</Grid>
</Window>

C'est aussi simple que ça: On déclare un contrôle Listbox, et à l'intérieur, on déclare trois éléments ListBoxItem chacun avec son propre texte. Néanmoins, comme les ListBoxItem sont en fait des ContentControl, nous pouvons leur définir un contenu personnalisé :

<Window x:Class="WpfTutorialSamples.ListBox_control.ListBoxSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBoxSample" Height="120" Width="200">
	<Grid Margin="10">
		<ListBox>
			<ListBoxItem>
				<StackPanel Orientation="Horizontal">
					<Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
					<TextBlock>ListBox Item #1</TextBlock>
				</StackPanel>
			</ListBoxItem>
			<ListBoxItem>
				<StackPanel Orientation="Horizontal">
					<Image Source="/WpfTutorialSamples;component/Images/bullet_green.png" />
					<TextBlock>ListBox Item #2</TextBlock>
				</StackPanel>
			</ListBoxItem>
			<ListBoxItem>
				<StackPanel Orientation="Horizontal">
					<Image Source="/WpfTutorialSamples;component/Images/bullet_red.png" />
					<TextBlock>ListBox Item #3</TextBlock>
				</StackPanel>
			</ListBoxItem>
		</ListBox>
	</Grid>
</Window>

Pour chacun des ListBoxItem, nous ajoutons maintenant un StackPanel, dans lequel nous ajoutons une Image et un TextBlock. Cela nous donne un contrôle total du contenu et du rendu du texte, comme vous pouvez le voir à partir des captures d'écrans, dans lesquelles on voit que différentes couleurs ont été utilisées pour chacun des numéros.

En étudiant la capture d'écran, vous pourrez remarquer une autre différence en comparant l'ItemsControl avec la ListBox : Par défaut, une bordure apparait autour du contrôle, le faisant paraître comme un contrôle plutôt que comme une donnée de sortie / un résultat.

Lier la ListBox à des données (Data Binding)

Définir manuellement les éléments d'une ListBox constitue un bon exemple, mais la plupart du temps, votre contrôle ListBox sera rempli avec des éléments d'une source de donnée utilisant le "data-binding" ou liaison de données. Par défaut, si vous liez une liste d’éléments à une ListBox, leur méthode ToString() sera utilisé pour représenter chaque élément. C'est rarement ce que l'on souhaite, mais heureusement, vous pouvez facilement déclarer un modèle/une maquette ("Template") qui sera utilisée pour assurer le rendu des éléments.

J'ai réutilisé l'exemple basé sur l'article à propos de ItemsControl, dans lequel nous avons construit une liste TODO plutôt cool en utilisant simplement une classe contenant du Code-behind et, dans ce cas précis, un contrôle ListBox pour la représentation visuelle. Ce qui donne l'exemple ci-dessous :

<Window x:Class="WpfTutorialSamples.ListBox_control.ListBoxDataBindingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBoxDataBindingSample" Height="150" Width="300">
    <Grid Margin="10">
		<ListBox Name="lbTodoList" HorizontalContentAlignment="Stretch">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<Grid Margin="0,2">
						<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>
			</ListBox.ItemTemplate>
		</ListBox>
	</Grid>
</Window>
using System;
using System.Windows;
using System.Collections.Generic;

namespace WpfTutorialSamples.ListBox_control
{
	public partial class ListBoxDataBindingSample : Window
	{
		public ListBoxDataBindingSample()
		{
			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 });

			lbTodoList.ItemsSource = items;
		}
	}

	public class TodoItem
	{
		public string Title { get; set; }
		public int Completion { get; set; }
	}
}

La magie opère en fait au sein du ItemTemplate que nous avons défini pour la Listbox. Ici, on spécifie que chaque élément de la ListBox doit consister en une Grid, divisée en 2 colonnes, avec un TextBlock montrant le titre en premier et une ProgressBar (barre de progression) montrant l'état d'avancement dans la seconde colonne. Pour obtenir les valeurs, on se sert d'une liaison de donnée (data-binding) très simple, qui est expliquée en détail dans la partie Data-Binding de ce tutoriel.

Dans le fichier de Code-behind, nous avons déclaré une simple classe TodoItem qui contient chaque élément de "chose à faire" (TODO Items). Dans le constructeur de la fenêtre, nous initialisons une liste à laquelle nous ajoutons 3 éléments (TODO items) ; nous assignons ensuite cette liste à ItemsSource de la ListBox. La combinaison de ItemsSource et du modèle ItemTemplate que nous avons spécifié dans la partie XAML sont les seules choses dont WPF a besoin pour afficher tous les éléments de notre liste (TODO list).

Il faut remarquer que nous avons réglé la propriété HorizontalContentAlignment de la ListBox à la valeur Stretch. En effet, l'alignement par défaut des éléments des ListBox est défini à la valeur gauche (Left), ce qui signifie que chaque élément occupe uniquement l'espace horizontal dont il a besoin. Le résultat dans ce cas là ? Pas exactement ce que nous voulons :

En utilisant la valeur étirement (Stretch) pour l'alignement, chaque élément est étiré pour utiliser tout l'espace disponible, comme nous avons pu le voir dans la copie d'écran précédente

Travailler avec la sélection de listbox

Tel que mentionné précédemment, une différence majeure entre l'ItemsControl et le ListBox est que le ListBox contrôle et affiche pour vous la fonctionnalité de sélection par l'utilisateur. Conséquemment, plusieurs des questions concernant le ListBox portent sur l'intégration de la fonctionnalité de sélection. Pour aider avec certaines des ces questions, j'ai créé un exemple plus complet, celui-ci vous démontrant certaines approches potentielles:

<Window x:Class="WpfTutorialSamples.ListBox_control.ListBoxSelectionSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBoxSelectionSample" Height="250" Width="450">
	<DockPanel Margin="10">
		<StackPanel DockPanel.Dock="Right" Margin="10,0">
			<StackPanel.Resources>
				<Style TargetType="Button">
					<Setter Property="Margin" Value="0,0,0,5" />
				</Style>
			</StackPanel.Resources>
			<TextBlock FontWeight="Bold" Margin="0,0,0,10">ListBox selection</TextBlock>
			<Button Name="btnShowSelectedItem" Click="btnShowSelectedItem_Click">Show selected</Button>
			<Button Name="btnSelectLast" Click="btnSelectLast_Click">Select last</Button>
			<Button Name="btnSelectNext" Click="btnSelectNext_Click">Select next</Button>
			<Button Name="btnSelectCSharp" Click="btnSelectCSharp_Click">Select C#</Button>
			<Button Name="btnSelectAll" Click="btnSelectAll_Click">Select all</Button>
		</StackPanel>
		<ListBox Name="lbTodoList" HorizontalContentAlignment="Stretch" SelectionMode="Extended" SelectionChanged="lbTodoList_SelectionChanged">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<Grid Margin="0,2">
						<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>
			</ListBox.ItemTemplate>
		</ListBox>
	</DockPanel>
</Window>
using System;
using System.Windows;
using System.Collections.Generic;

namespace WpfTutorialSamples.ListBox_control
{
	public partial class ListBoxSelectionSample : Window
	{
		public ListBoxSelectionSample()
		{
			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 });

			lbTodoList.ItemsSource = items;
		}

		private void lbTodoList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
		{
			if(lbTodoList.SelectedItem != null)
				this.Title = (lbTodoList.SelectedItem as TodoItem).Title;
		}

		private void btnShowSelectedItem_Click(object sender, RoutedEventArgs e)
		{
			foreach(object o in lbTodoList.SelectedItems)
				MessageBox.Show((o as TodoItem).Title);
		}

		private void btnSelectLast_Click(object sender, RoutedEventArgs e)
		{
			lbTodoList.SelectedIndex = lbTodoList.Items.Count - 1;
		}

		private void btnSelectNext_Click(object sender, RoutedEventArgs e)
		{
			int nextIndex = 0;
			if((lbTodoList.SelectedIndex >= 0) && (lbTodoList.SelectedIndex < (lbTodoList.Items.Count - 1)))
				nextIndex = lbTodoList.SelectedIndex + 1;
			lbTodoList.SelectedIndex = nextIndex;
		}

		private void btnSelectCSharp_Click(object sender, RoutedEventArgs e)
		{
			foreach(object o in lbTodoList.Items)
			{
				if((o is TodoItem) && ((o as TodoItem).Title.Contains("C#")))
				{
					lbTodoList.SelectedItem = o;
					break;
				}
			}
		}

		private void btnSelectAll_Click(object sender, RoutedEventArgs e)
		{
			foreach(object o in lbTodoList.Items)
				lbTodoList.SelectedItems.Add(o);
		}


	}

	public class TodoItem
	{
		public string Title { get; set; }
		public int Completion { get; set; }
	}
}

Comme vous pouvez le voir, j'ai défini une gamme de boutons à droite de la ListBox, pour obtenir ou manipuler la sélection. J'ai également changé le SelectionMode en Extended, pour permettre la sélection de plusieurs éléments. Cela peut être fait soit par programme, comme je le fais dans l'exemple, ou par l'utilisateur final, en maintenant la touche [Ctrl] ou [Maj] enfoncée tout en cliquant sur les éléments.

Pour chacun des boutons, j'ai défini un gestionnaire de clics dans le code-behind. Chaque action doit être assez explicite et le code C # utilisé est assez simple, mais si vous avez toujours des doutes, essayez d'exécuter l'exemple sur votre propre machine et testez les différentes possibilités de l'exemple.

Sommaire

Le contrôle ListBox ressemble beaucoup à ItemsControl et plusieurs des mêmes techniques peuvent être utilisées. Le ListBox offre un peu plus de fonctionnalités par rapport au ItemsControl, en particulier la gestion de la sélection. Pour encore plus de fonctionnalités, comme les en-têtes de colonne, vous devriez jeter un œil au contrôle ListView, qui est donné une description très détaillée plus loin dans ce tutoriel avec plusieurs articles expliquant toutes les fonctionnalités.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!