Binding sur Grid via ListBox2 septembre 2010

Le contrôle Grid étant dépourvu de propriété ItemsSource, je vais vous présenter une manière de réaliser un Binding d’une source de données (Collection d’objets) sur ce contrôle, en passant par le contrôle ListBox et ses différents templates.
La source de données
Imaginons que nous souhaitions créer un damier avec des pions dessus. Chaque pion serait représenté par une classe « Pion » composée entre autres de deux propriétés X et Y représentant les coordonnées de ce dernier sur le damier.
class Pion
{
public int X { get; set; }
public int Y { get; set; }
}
L’objectif sera de placer correctement les pions dans les « cases » d’un contrôle Grid; X et Y seront respectivement les propriétés affectées à Grid.Column et Grid.Row de chaque objets enfant de la grille.
L’interface de Binding
Autrement appelé le ViewModel, il s’agit d’un objet sur lequel sera bindée l’interface graphique afin de retranscrire le contenu de notre damier.
Voici le code C# :
class VMMainWindow
{
static VMMainWindow() { Instance = new VMMainWindow(); }
public static VMMainWindow Instance { get; private set; }
private VMMainWindow()
{
Pions = new List<Pion>();
Pions.Add(new Pion { X = 0, Y = 0 });
Pions.Add(new Pion { X = 1, Y = 0 });
Pions.Add(new Pion { X = 2, Y = 4 });
Pions.Add(new Pion { X = 0, Y = 1 });
Pions.Add(new Pion { X = 1, Y = 1 });
}
public List<Pion> Pions { get; private set; }
}
L’interface graphique
Le code XAML se suffit à lui même pour ce qui est de sa connection avec le ViewModel. On place dans la propriété DataContext de la fenêtre (Window), le singleton du ViewModel : VMMainWindow.Instance. Ainsi, l’intégralités des contrôles de la fenêtre aura comme source de données ce singleton avec ses propriétés.
Voici le code XAML :
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:WpfApplication1.ViewModel"
DataContext="{x:Static vm:VMMainWindow.Instance}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox ItemsSource="{Binding Path=Pions}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Grid.Column" Value="{Binding Path=X}" />
<Setter Property="Grid.Row" Value="{Binding Path=Y}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Ellipse Width="20" Height="20" Fill="Red" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Une petite explication semble nécessaire pour comprendre pourquoi l’on passe par un Style pour positionner les Ellipses représentant les pions. En fait l’explication est relativement simple, l’Ellipse dans le ItemTemplate n’est pas directement ajouter à la Grid, elle est préalablement encapsulée dans un ListBoxItem. On ne peut donc pas définir Grid.Row et Grid.Column directement sur l’élément Ellipse.
En revanche, ItemContainerStyle définit justement le style pour l’élément contenant le ItemTemplate, et dans le cas du contrôle ListBox, il s’agit d’un ListBoxItem.
Au résultat, vous obtiendrez cet affichage :

Aucun commentaire pour le moment. Soyez le/la premi(er/ère).