[WPF] Comment sélectionner un item dans un Treeview lié à une Collection/ObservableCollection ?
Lorsque l'on travaille avec un TreeView (ou une ListBox), on est souvent amené à écrire un petit bout de code permettant de sélectionner un item particuler. Avec WPF (Windows Presentation Foundation), on peut tout à faire le faire au moyen d'un code ressemblant à ceci:
TreeViewItem tvi = this.tv.ItemContainerGenerator.ContainerFromIndex(3) as TreeViewItem;
Bien que fonctionnel, ce code pose un problème: en effet, il sous-entends que votre Treeview est remplie de TreeViewItem. Cela peut vous sembler tout à fait normal mais attention, n'oubliez pas qu'avec WPF, la façon dont les contrôles affichent leur contenu est complètement différente: on peut donc retrouver des CheckBox, des Boutons, etc... à la place de ces TreeViewItem.
Prenez le cas où vous utilisez une ObservableCollection que vous allez lier à votre TreeView:
public class Item
{
public string Name { get; set; }
}
public class MyCollection : ObservableCollection<Item>
{
public ObservableCollection<Item> MyItems { get; set; }
public MyCollection()
{
MyItems = new ObservableCollection<Item>();
MyItems.Add(new Item() { Name = "Element 1" });
MyItems.Add(new Item() { Name = "Element 2" });
MyItems.Add(new Item() { Name = "Element 3" });
MyItems.Add(new Item() { Name = "Element 4" });
MyItems.Add(new Item() { Name = "Element 5" });
}
}
Vous allez ensuite logiquement instancier votre ObservableCollection et la mettre comme DataContext sur votre TreeView. Cependant, si vous reprenez le code permettant de sélectionner un élément particulier, vous vous rendrez compte qu'il ne fonctionne pas. En effet, le template par défaut, lorsque l'on utilise une collection liée, n'utilise pas de TreeViewItem: le cast que vous réaliser ne fonctionne donc pas (tvi est null).
Pour corriger ce petit "problème", voici la solution que je vous propose: dans les ressources de votre TreeView/Window, créer un DataTemplate comprenant un TreeViewItem incorporant un TextBlock (bindé à la propriété qui vous intéresse) et utilisez-le dans votre TreeView:
<DataTemplate x:Key="template">
<TreeViewItem IsExpanded="True">
<TextBlock Text="{Binding Name}" Foreground="Red" />
</TreeViewItem>
</DataTemplate>
<TreeView x:Name="tv" ItemsSource="{Binding Path=MyItems}" ItemTemplate="{StaticResource template}" Margin="0,-2,0,2" />
Ensuite, remplacez le code de sélection d'un élément par celui-ci:
TreeViewItem tvi = this.tv.ItemContainerGenerator.ContainerFromIndex(3) as TreeViewItem;
Et là, plus de problème: l'élément que vous avez indiqué en paramètre de la méthode ContainerFromIndex est sélectionné. Le pourquoi du comment est simple: avant, cette méthode ne renvoyait rien mais grâce à l'utiliation du DataTemplate, nous spécifions explicitement que nous avons un TreeViewItem (comprenant nos informations).
Et le tour est joué 
A+
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :