0

What do I have to change in the following code to make the "A Child Section" node appear as a child of the First Section and Second Section:

The following code gives me a XamlParseException.

XAML:

<Window x:Class="TestTr32322.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestTr32322"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <HierarchicalDataTemplate x:Key="sectionTemplate" 
            ItemsSource="{Binding ChildSections}"
            DataType="{x:Type local:Section}">
            <TextBlock Text="{Binding Title}" />
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <TreeView ItemsSource="{Binding Sections}" 
                  ItemTemplate="{StaticResource sectionTemplate}">
        </TreeView>
    </Grid>
</Window>

Code Behind:

using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace TestTr32322
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        #region ViewModelProperty: Sections
        private ObservableCollection<Section> _sections = new ObservableCollection<Section>();
        public ObservableCollection<Section> Sections
        {
            get
            {
                return _sections;
            }

            set
            {
                _sections = value;
                OnPropertyChanged("Sections");
            }
        }
        #endregion

        public Window1()
        {
            InitializeComponent();
            DataContext = this;

            Sections = Section.GetSections();
        }

        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

    }

    public class Section
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public ObservableCollection<Section> ChildSections { get; set; }

        public static ObservableCollection<Section> GetSections()
        {
            ObservableCollection<Section> sections = new ObservableCollection<Section>();

            {
                Section section = new Section();
                section.Title = "First Section";
                section.ChildSections.Add(new Section
                {
                    Title = "A Child Section",
                    Description = "this is the description",
                    ChildSections = new ObservableCollection<Section>()
                });
                sections.Add(section);
            }

            {
                Section section = new Section();
                section.Title = "Second Section";
                section.ChildSections.Add(new Section
                {
                    Title = "A Child  Section",
                    Description = "this is the description",
                    ChildSections = new ObservableCollection<Section>()
                });
                sections.Add(section);
            }

            return sections;
        }
    }

}
Edward Tanguay
  • 189,012
  • 314
  • 712
  • 1,047

2 Answers2

1

It looks like you need HierarchicalDataTemplate. They have an example in the article...

Anvaka
  • 15,658
  • 2
  • 47
  • 56
  • thanks, I added HierarchicalDataTemplate based on what I could get from this article http://bea.stollnitz.com/blog/?p=18 but it still gives me the same result (code changed above) – Edward Tanguay Feb 23 '10 at 13:17
  • I see. Convert ChildSection to ObservableCollection and bind HierarchicalDataTemplate.ItemsSource to it.. Will it help? – Anvaka Feb 23 '10 at 13:22
  • I made those changes to my code above but now it gives me a XamlParseException, as if ChildSections are null on some Sections, but they seem to be all initialized. – Edward Tanguay Feb 23 '10 at 13:34
  • Yah, it looks like you forgot to initialize Section.ChildSections collection before adding anything to it... – Anvaka Feb 23 '10 at 13:42
  • excellent, I just had to convert ChildSections into a full INotifyPropertyChanged property and it worked, thanks for you help! – Edward Tanguay Feb 23 '10 at 14:03
1

Have a look at this question and the accepted answer. It should point you into the right direction, too.

The basic idea is to define HierarchicalDataTemplates with an ItemsSource property and make them match by type.

In your case:

<HierarchicalDataTemplate DataType="{x:Type local:Section}" 
                          ItemsSource="{Binding ChildSection}">
    <TextBlock Text="{Binding Path=Title}" />
</HierarchicalDataTemplate>

Edit: In your code you should create a new collection before adding a value to it:

// The new was missing and resulted in the end in your XAML Parse Exception
section.ChildSections = new ObservableCollection<Section>();
section.ChildSections.Add( /*... */);
Community
  • 1
  • 1
olli-MSFT
  • 2,556
  • 19
  • 19
  • I'll take a look, meanwhile I make your change and posted above but it's still giving me a XamlParseException saying "an object was not instantiated". – Edward Tanguay Feb 23 '10 at 13:38
  • I took a look a that example, I actually only need one type: Sections under Sections under Sections. Is it still necessary to define the type then, I thought the x:key was enough to connect the TreeView and the HierarchicalDataTemplate. – Edward Tanguay Feb 23 '10 at 13:39
  • Yes, in this case x:Key is enough. If you have heterogeneous nodes in your tree, however, x:Key won't work. – olli-MSFT Feb 23 '10 at 13:56