WPF TreeView HierarchicalDataTemplate – liaison à un object avec plusieurs collections enfant

J’essaie d’obtenir un TreeView pour lier ma collection afin que tous les groupes montrent des groupes nesteds et chaque groupe affichera l’entrée.

Comment puis-je utiliser le HierarchicalDataTemplate pour que TreeView traite à la fois la collection SubGroups et Ensortinges?

Les groupes affichent des sous-groupes et des entrées:

 Example: Group1 --Entry --Entry Group2 --Group4 ----Group1 ------Entry ------Entry ----Entry ----Entry --Entry --Entry Group3 --Entry --Entry 

Objets:


 namespace TaskManager.Domain { public class Entry { public int Key { get; set; } public ssortingng Name { get; set; } } } namespace TaskManager.Domain { public class Group { public int Key { get; set; } public ssortingng Name { get; set; } public IList SubGroups { get; set; } public IList Ensortinges { get; set; } } } 

Données de test:


 namespace DrillDownView { public class TestData { public IList Groups = new List(); public void Load() { Group grp1 = new Group() { Key = 1, Name = "Group 1", SubGroups = new List(), Ensortinges = new List() }; Group grp2 = new Group() { Key = 2, Name = "Group 2", SubGroups = new List(), Ensortinges = new List() }; Group grp3 = new Group() { Key = 3, Name = "Group 3", SubGroups = new List(), Ensortinges = new List() }; Group grp4 = new Group() { Key = 4, Name = "Group 4", SubGroups = new List(), Ensortinges = new List() }; //grp1 grp1.Ensortinges.Add(new Entry() { Key=1, Name="Entry number 1" }); grp1.Ensortinges.Add(new Entry() { Key=2, Name="Entry number 2" }); grp1.Ensortinges.Add(new Entry() { Key=3,Name="Entry number 3" }); //grp2 grp2.Ensortinges.Add(new Entry(){ Key=4, Name = "Entry number 4"}); grp2.Ensortinges.Add(new Entry(){ Key=5, Name = "Entry number 5"}); grp2.Ensortinges.Add(new Entry(){ Key=6, Name = "Entry number 6"}); //grp3 grp3.Ensortinges.Add(new Entry(){ Key=7, Name = "Entry number 7"}); grp3.Ensortinges.Add(new Entry(){ Key=8, Name = "Entry number 8"}); grp3.Ensortinges.Add(new Entry(){ Key=9, Name = "Entry number 9"}); //grp4 grp4.Ensortinges.Add(new Entry(){ Key=10, Name = "Entry number 10"}); grp4.Ensortinges.Add(new Entry(){ Key=11, Name = "Entry number 11"}); grp4.Ensortinges.Add(new Entry(){ Key=12, Name = "Entry number 12"}); grp4.SubGroups.Add(grp1); grp2.SubGroups.Add(grp4); Groups.Add(grp1); Groups.Add(grp2); Groups.Add(grp3); } } } 

XAML:


                     

XAML.CS:


 public partial class Window2 : Window { public Window2() { InitializeComponent(); LoadView(); } private void LoadView() { TestData data = new TestData(); data.Load(); GroupView.ItemsSource = data.Groups; } } 

Un HierarchicalDataTemplate est une façon de dire “voici comment vous rendez ce type d’object et voici une propriété qui peut être sondée pour trouver les noeuds enfants sous cet object”

Par conséquent, vous avez besoin d’une propriété unique qui renvoie les «enfants» de ce nœud. par exemple (si vous ne pouvez pas créer à la fois un groupe et une entrée à partir d’un type de noeud commun)

 public class Group{ .... public IList Items { get { IList childNodes = new List(); foreach (var group in this.SubGroups) childNodes.Add(group); foreach (var entry in this.Ensortinges) childNodes.Add(entry); return childNodes; } } 

Ensuite, vous n’avez pas besoin d’un HierDataTemplate pour l’entrée car une entrée n’a pas d’enfant. Donc, le XAML doit être modifié pour utiliser la nouvelle propriété Items et un DataTemplate for Entry:

           

Et voici à quoi ça ressemble. Capture d'écran de la sortie

Je pense que vous êtes la plupart du temps là-bas … avec un tout petit peu de retravail, vous devriez obtenir ce travail assez facilement …

Je vous suggère de créer une classe abstraite de base (ou une interface, selon votre préférence) et de l’hériter / l’implémenter à la fois pour la classe Group et Entry …

De cette façon, vous pouvez exposer une propriété dans votre object Groupe.

 public ObservableCollection Children { get; set; } 

^ à ce stade, vous pouvez décider si cela remplace vos listes de sous-groupes et d’entrées, ou simplement les append ensemble et les retourner dans la propriété getter …

Il ne vous rest plus qu’à remplir la collection Children avec des objects Group ou Entry et le HierarchicalDataTemplate sera rendu correctement lorsque les objects seront placés dans TreeView.

Une dernière pensée, si Entry est toujours le «niveau inférieur» de l’arborescence (c’est-à-dire sans enfants), vous n’avez pas besoin de définir un HierarchicalDataTemplate pour l’object Entry, un DataTemplate suffit.

J’espère que cela t’aides 🙂

Voici une autre implémentation de la réponse de Gishu qui renvoie un IEnumerable plutôt qu’un IList et utilise le mot-clé yield pour simplifier le code:

 public class Group { ... public IEnumerable Items { get { foreach (var group in this.SubGroups) yield return group; foreach (var entry in this.Ensortinges) yield return entry; } } } 

Ce post m’a aidé à chercher une solution pour ce même problème: http://blog.pmunin.com/2012/02/xaml-binding-to-compositecollection.html

en utilisant MultiBinding et CompositeCollectionConverter ..

/ Observe Anders