0

In my program I have a TreeView with data backings (View Model & Data Model). Each item added to the TreeView gets a child item added with it, but for some reason the children are not reflecting during run time. However, I am able to see the children during debugging and my "Children" property in the TreeView's data model includes NotifyPropertyChange in it's setter.

Note: Earlier I had a similar problem where newly added nodes (parents of these children) wouldn't be displayed either. This problem was corrected by setting DisplayMemberPath="DisplayName.Value" in the tree's xaml.

TreeView's xaml:

TreeView ItemsSource="{Binding UserControl_DataModel.TreeViewViewModel.ObservableCollection<TreeViewDataModel>}" DisplayMemberPath="DisplayName.Value".../>

This is where new nodes are created and added to the TreeView (TreeViewViewModel):

private TreeViewDataModel createNewNode(StringItem nodeName)
{
    var newNode = new TreeViewDataModel ()
    {
        DisplayName = nodeName
    };

    newNode.Children.Add(new TreeViewDataModel () { DisplayName = nodeName});

    return newNode;
}

public void addNewLocNode(StringItem nodeName)
{
    TreeObservableCollection.Add(createNewNode(nodeName));
}

Note: StringItem is a custom class. In StringItem, Value returns the string value of the item. (Ex: StringItem.Value)

Children property in TreeViewDataModel:

public ObservableCollection<TreeViewDataModel> Children
{
    get { return _children ?? (_children = new ObservableCollection<TreeViewDataModel>()); }
    set
    {
        _children = value;
        NotifyPropertyChange(() => Children);
    }
}

Why aren't the child nodes showing up in my TreeView, and how can I fix this?

Eric after dark
  • 1,768
  • 4
  • 31
  • 79

1 Answers1

0

You don't have enough code for me to know exactly how you have things set up. I tried to keep it similar to what you already have. I think you should be able to figure it out though.

Screenshot:

enter image description here

XAML:

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:WpfApplication9"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TreeView ItemsSource="{Binding TreeObservableCollection}"> <!-- DisplayMemberPath="DisplayName.Value" - Can't set both DisplayMemberPath and ItemTemplate -->
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type app:TreeViewDataModel}" ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding DisplayName.Value}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>

CODE:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<TreeViewDataModel> TreeObservableCollection { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            TreeObservableCollection = new ObservableCollection<TreeViewDataModel>();
            this.DataContext = this;
            this.Loaded += MainWindow_Loaded;
        }
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            addNewLocNode(new StringItem("A"));
            addNewLocNode(new StringItem("B"));
            addNewLocNode(new StringItem("C"));
            addNewLocNode(new StringItem("D"));
        }
        private TreeViewDataModel createNewNode(StringItem nodeName)
        {
            var newNode = new TreeViewDataModel()
            {
                DisplayName = nodeName
            };
            newNode.Children.Add(new TreeViewDataModel() { DisplayName = nodeName });
            return newNode;
        }

        public void addNewLocNode(StringItem nodeName)
        {
            TreeObservableCollection.Add(createNewNode(nodeName));
        }
    }
    public class StringItem
    {
        public string Value { get; set; }
        public StringItem(string val)
        {
            Value = val;
        }
    }
    public class TreeViewDataModel : System.ComponentModel.INotifyPropertyChanged
    {
        public StringItem DisplayName { get; set; }
        private ObservableCollection<TreeViewDataModel> _children;
        public ObservableCollection<TreeViewDataModel> Children
        {
            get { return _children ?? (_children = new ObservableCollection<TreeViewDataModel>()); }
            set
            {
                _children = value;
                NotifyPropertyChange("Children");
            }
        }
        private void NotifyPropertyChange(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(name));
        }
        #region INotifyPropertyChanged Members

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

Alt-way:

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:WpfApplication9"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type app:TreeViewDataModel}" ItemsSource="{Binding Children}">
        <TextBlock Text="{Binding DisplayName.Value}" />
    </HierarchicalDataTemplate>
</Window.Resources>
<Grid>
    <TreeView ItemsSource="{Binding TreeObservableCollection}" />
</Grid>

J.H.
  • 4,232
  • 1
  • 18
  • 16
  • Why do I need to set an `ItemTemplate`? I don't have one set up in any of my other `TreeViews` and they are working just fine. – Eric after dark Jul 11 '14 at 19:11
  • Do they have children too? IDK.. I just took a TreeView w/children that I had in some of my code and adjusted it. – J.H. Jul 11 '14 at 19:13
  • Yes they have children as well – Eric after dark Jul 11 '14 at 19:17
  • Are you adding them in code? Or with a binding? AFAIK, you have to have a HierarchicalDataTemplate for the binding. – J.H. Jul 11 '14 at 19:22
  • Yes I'm adding them with `newNode.Children.Add(new TreeViewDataModel () { DisplayName = nodeName});`, upon creation of the main parent node. I think you are on the right track, I did forget to create a `HierarchicalDataTemplate` for this `treeView` so I just created one. Unfortunately, still no children. – Eric after dark Jul 11 '14 at 19:27
  • I added an Alt-way of doing it, with the hierachicaldatatemplate as a resource. – J.H. Jul 11 '14 at 19:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57176/discussion-between-eric-after-dark-and-j-h). – Eric after dark Jul 11 '14 at 19:31