Les
ItemsControls(Listbox, Treeview, Menu,...) font partie des contrôles les plus utilisés.
Leurs enfants, à savoir les objets/contrôles que l'on place dedans, peuvent être intéractif et déclencher des événements auxquels on veut s'abonner.Il y a alors deux cas de figures :
- Les éléments sont placés à la main dans le XAML(par exemple lorsque l'on créé un menu) et on peut ajouter le handler directement dessus (sur chaque élément).
- Les éléments sont placés de façon dynamiques via une liste : pas de moyen facile de s'abonner aux événements,
- Les élements placés sont des objets métiers et un DataTemplate et utilisé pour les afficher. Dans ce cas les gestionnaires d'événements placés dans le DataTemplate ne fonctionnent pas.
Dans cet article nous allons voir une méthode qui fonctionne dans tout les cas de figure et qui reste très facile à mettre en oeuvre.
L'idée principale est de passer par le
style du contrôle parent (l'itemControl) et de rajouter un gestionnaire d'événements pour l'événement visé.
Prenons par exemple un TreeView sur lequel nous voulons nous abonner à l'événement MouseDown des enfants. Nous aurons alors le code XAML suivant :
<TreeView>
<TreeView.Style>
<Style>
<EventSetter Event="TreeViewItem.MouseDown" Handler="TreeViewItem_MouseDown"/>
</Style>
</TreeView.Style>
<TreeViewItem Header="Item niveau 1 : 1" />
<TreeViewItem Header="Item niveau 1 : 2"/>
<TreeViewItem Header="Item niveau 1 : 3"/>
<TreeViewItem Header="Item niveau 1 : 4">
<TreeViewItem Header="Item niveau 2 : 4A"/>
<TreeViewItem Header="Item niveau 2 : 4B"/>
<TreeViewItem Header="Item niveau 2 : 4C"/>
</TreeViewItem>
<TreeViewItem Header="Item niveau 1 : 5"/>
</TreeView>
Et dans notre code-behind, on peut récupérer l'
item ayant lancé l'événement avec la propriété Source RouredEventArgs. Cela donne ce code :
private void TreeViewItem_MouseDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem treeViewItem = e.Source as TreeViewItem;
MessageBox.Show("J'ai déclenché l'événement : " + treeViewItem.Header);
} Pour comparaison, si l'on s'abonnait sur chacun des items on aurait un XAML beaucoup plus fastidieux à taper :<TreeView>
<TreeViewItem Header="Item niveau 1 : 1" MouseDown="TreeViewItem_MouseDown" />
<TreeViewItem Header="Item niveau 1 : 2" MouseDown="TreeViewItem_MouseDown" />
<TreeViewItem Header="Item niveau 1 : 3" MouseDown="TreeViewItem_MouseDown" />
<TreeViewItem Header="Item niveau 1 : 4" MouseDown="TreeViewItem_MouseDown" >
<TreeViewItem Header="Item niveau 2 : 4A" MouseDown="TreeViewItem_MouseDown" />
<TreeViewItem Header="Item niveau 2 : 4B" MouseDown="TreeViewItem_MouseDown" />
<TreeViewItem Header="Item niveau 2 : 4C" MouseDown="TreeViewItem_MouseDown" />
</TreeViewItem>
<TreeViewItem Header="Item niveau 1 : 5" MouseDown="TreeViewItem_MouseDown" />
</TreeView>