namespace TaskManager.Domain { public class Entry { public int Key { get; set; } public string Name { get; set; } } } namespace TaskManager.Domain { public class Group { public int Key { get; set; } public string Name { get; set; } public IList SubGroups { get; set; } public IList Entries { get; set; } } }
Dati di 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(), Entries = new List() }; Group grp2 = new Group() { Key = 2, Name = "Group 2", SubGroups = new List(), Entries = new List() }; Group grp3 = new Group() { Key = 3, Name = "Group 3", SubGroups = new List(), Entries = new List() }; Group grp4 = new Group() { Key = 4, Name = "Group 4", SubGroups = new List(), Entries = new List() }; //grp1 grp1.Entries.Add(new Entry() { Key=1, Name="Entry number 1" }); grp1.Entries.Add(new Entry() { Key=2, Name="Entry number 2" }); grp1.Entries.Add(new Entry() { Key=3,Name="Entry number 3" }); //grp2 grp2.Entries.Add(new Entry(){ Key=4, Name = "Entry number 4"}); grp2.Entries.Add(new Entry(){ Key=5, Name = "Entry number 5"}); grp2.Entries.Add(new Entry(){ Key=6, Name = "Entry number 6"}); //grp3 grp3.Entries.Add(new Entry(){ Key=7, Name = "Entry number 7"}); grp3.Entries.Add(new Entry(){ Key=8, Name = "Entry number 8"}); grp3.Entries.Add(new Entry(){ Key=9, Name = "Entry number 9"}); //grp4 grp4.Entries.Add(new Entry(){ Key=10, Name = "Entry number 10"}); grp4.Entries.Add(new Entry(){ Key=11, Name = "Entry number 11"}); grp4.Entries.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 è un modo per dire ‘questo è come si esegue il rendering di questo tipo di object e qui è una proprietà che può essere esplorata per trovare i nodes figlio sotto questo object’
Pertanto è necessaria una singola proprietà che restituisca i “figli” di questo nodo. es. (Se non puoi fare in modo che Gruppo e Entrata derivino da un tipo di nodo comune)
public class Group{ .... public IList
Quindi non è necessario un HierDataTemplate per la voce poiché una voce non ha figli. Quindi è necessario modificare XAML per utilizzare la nuova proprietà Items e un DataTemplate per l’Entry:
Ed ecco come appare.
Penso che tu sia la maggior parte del modo lì … con un po ‘di rilavorazione dovresti farlo funzionare abbastanza facilmente …
Ti suggerisco di creare una class astratta di base (o un’interfaccia, quella che preferisci) e di ereditarla / implementarla sia per la class di gruppo che per quella di entrata …
In questo modo, puoi esporre una proprietà all’interno dell’object del tuo gruppo
public ObservableCollection Children { get; set; }
^ a questo punto, puoi prendere una decisione se questo sostituisce i tuoi elenchi di sottogruppi e voci, o semplicemente li aggiunge e li restituisce nel getter della proprietà …
Ora tutto ciò che serve è compilare la raccolta Children con oggetti Group o Entry e HierarchicalDataTemplate eseguirà correttamente il rendering quando gli oggetti vengono posizionati nel TreeView.
Un ultimo pensiero, se Entry è sempre il ‘livello inferiore’ dell’albero (cioè non ha figli), quindi non è necessario definire un HierarchicalDataTemplate per l’object Entry, un DataTemplate sarà sufficiente.
Spero che questo ti aiuti 🙂
Ecco un’implementazione alternativa della risposta di Gishu che restituisce un object IEnumerable piuttosto che un IList e utilizza la parola chiave yield per semplificare il codice:
public class Group { ... public IEnumerable Items { get { foreach (var group in this.SubGroups) yield return group; foreach (var entry in this.Entries) yield return entry; } } }