1

I'm using a WPF TreeView control, which I've bound to a simple tree structure based on ObservableCollections. Here's the XAML:


<TreeView Name="tree" Grid.Row="0"> 
    <TreeView.ItemTemplate> 
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}"> 
            <TextBlock Text="{Binding Path=Text}"/> 
        </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView>  

And the tree structure:


public class Node : IEnumerable { 
    private string text; 
    private ObservableCollection<Node> children; 
    public string Text { get { return text; } } 
    public ObservableCollection<Node> Children { get { return children; } } 
    public Node(string text, params string[] items){ 
        this.text = text; 
        children = new ObservableCollection<Node>(); 
        foreach (string item in items) 
            children.Add(new Node(item)); 
    } 
    public IEnumerator GetEnumerator() { 
        for (int i = 0; i < children.Count; i++) 
            yield return children[i]; 
    } 
} 

I set the ItemsSource of this tree to be the root of my tree structure, and the children of that become root-level items in the tree (just as I want):


private Node root; 

root = new Node("Animals"); 
for(int i=0;i<3;i++) 
    root.Children.Add(new Node("Mammals", "Dogs", "Bears")); 
tree.ItemsSource = root; 

I can add new children to the various non-root nodes of my tree structure, and they appear in the TreeView right where they should.

root.Children[0].Children.Add(new Node("Cats", "Lions", "Tigers"));  

But, if I add a child to the root node:

root.Children.Add(new Node("Lizards", "Skinks", "Geckos")); 

The item does not appear, and nothing I've tried (such as setting the ItemsSource to null and then back again) has caused it to appear.

If I add the lizards before setting the ItemsSource, they show up, but not if I add them afterwards.

The cats appear, but not the lizards

Any ideas?

Joel Rein
  • 3,608
  • 1
  • 26
  • 32
  • what observableCollection are you using, this one http://msdn.microsoft.com/en-us/library/ms668604.aspx ? cause in your code above that looks like a non-generic version, have you rolled your own? – Aran Mulholland Dec 14 '09 at 06:25
  • That was my bad - the type parameter was not shown because of the angle brackets. Yes, I'm using the standard, generic ObservableCollection. – Joel Rein Dec 14 '09 at 07:18
  • Did you ever find the solution to this problem? I have exactly the same problem and would appreciate any guidance you can offer. Thanks. – Tim Coulter Jan 26 '10 at 07:49
  • Josh Einstein's answer fixed my problem - setting ItemsSource to root.Children. Don't know if that will fix your issue. – Joel Rein Feb 12 '10 at 06:06

2 Answers2

3

You are setting ItemsSource = root which happens to implement IEnumerable but is not in and of itself observable. Even though you have a Children property which is observable, that's not what you're binding the TreeView to so the TreeView doesn't have any way of listening to changes that occur through the Children property.

I would drop IEnumerable from the Node class altogether. Then set treeView.ItemsSource = root.Children;

Josh
  • 68,005
  • 14
  • 144
  • 156
2

if 'root' is an ObservableCollection your treeview will update. is 'root' an observable collection, or is root a node that is in an observable collection? seeing your binding for the items source would help to answer this question. as you are assigning it in code you might just be setting it to be a single element, not a collection

Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228
  • I've updated the question with the relevant details - "root" is just a Node like all the others. It doesn't show up in the TreeView itself, but that's fine. If I create a observable NodeCollection and use that as the root, it doesn't make any difference. – Joel Rein Dec 14 '09 at 04:42