Reputation: 394
I've been trying to get my first TreeView
to work, at first without the ViewModel. But no matter what I do, it doesn't show any children, even though the binding is correct.
I'm using two Item
templates, one for hierarchical and another for data. You can see the important parts for both below:
class GrupoTag
{
public string Nome { get; set; }
public GrupoTag Pai { get; set; }
public List<Tag> ListaFilhos { get; set; }
public List<GrupoTag> SubGrupos { get; set; }
public GrupoTag(string nome)
{
Nome = nome;
ListaFilhos = new List<Tag>();
SubGrupos = new List<GrupoTag>();
}
public List<object> Filhos
{
get
{
List<object> lista = new List<object>();
foreach (GrupoTag subGrupo in SubGrupos)
lista.Add(subGrupo);
foreach (Tag filho in ListaFilhos)
lista.Add(filho);
}
}
}
class Tag
{
public GrupoTag Pai { get; set; }
public string Nome { get; set; }
public Tag(string nome)
{
Nome = nome;
}
public Tag(GrupoTag pai, string nome)
{
Pai = pai;
Nome = nome;
}
}
The XAML binding to all of this:
<TreeView Name="MenuTags">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="xml2Excel2:GrupoTag" ItemsSource="{Binding Filhos}">
<TextBlock Text="{Binding Nome}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="xml2Excel2:Tag">
<TextBlock Text="{Binding Nome}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
But the property "Filhos" on the GrupoTag
class is never accessed. I've tried putting a breakpoint in there, throwing an exception, but it's simply never called. And the TreeView
only displays the names of the collection of GrupoTag
s I assigned to it as its ItemSource
in code-behind.
MenuTags.ItemsSource = arvoreTeste.SubGrupos;
I've read all the related questions and corrected the code for the respective errors, but I'm still lost here.
EDIT 1: So I modified the code of the classes to conform to the simple interface below:
class ITag
{
public string Nome { get; set; }
public ObservableCollection<ITag> Filhos { get; set; }
}
As per Benin comment, GrupoTag now uses a single property stored in a ObservableCollection
to represent its children. And, as per Adnan answer removed the DataType
from the XAML TreeView
. Now it looks like this:
<TreeView Name="ArvoreTags">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Nome}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
It works, the TreeView
is functional. But I don't know why.
Upvotes: 2
Views: 1900
Reputation: 86600
I found a simple answer to my specific case, not yours it seems
The children must be a "property".
So:
public ObservableCollection<Tag> ListaFilhos ; //doesn't work
public ObservableCollection<Tag> ListaFilhos {get; set;} //works
Upvotes: 0
Reputation: 21
You need to give your TreeView ItemSource and DataType. And I would agree to Berins comment , you should avoid making new list to each access to Filhos property. TreeView works very good with Polymorphis, I mean with data types.
<TreeView DockPanel.Dock="Top"
DataContext="{Binding ProjectNodes_DataContext}"
ItemsSource="{Binding Nodes}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:ProjectNode}" ItemsSource="{Binding SubItems}">
<StackPanel>
<TextBlock Text="{Binding Header}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
My Property is:
private ProjectNodesVM mProjectNodes_DataContext;
public ProjectNodesVM ProjectNodes_DataContext
{
get { return mProjectNodes_DataContext; }
protected set
{
SetProperty(ref mProjectNodes_DataContext, value);
}
}
and class ProjectNodesVM has:
public ObservableCollection<ProjectNode> Nodes {
get { return mNodes; }
protected set { SetProperty(ref mNodes, value); }
}
inside ProjectNode class i have:
private string mHeader;
public string Header
{
get { return mHeader; }
set { SetProperty(ref mHeader, value); }
}
Upvotes: 2