manoftheyear
manoftheyear

Reputation: 394

WPF: TreeView does not show any children

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 GrupoTags 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 TreeViewis functional. But I don't know why.

Upvotes: 2

Views: 1900

Answers (2)

Daniel M&#246;ller
Daniel M&#246;ller

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

Adnan Poljak
Adnan Poljak

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

Related Questions