【问题标题】:How can I get child tree nodes to appear in a WPF TreeView when binding to an ObservableCollection?绑定到 ObservableCollection 时,如何让子树节点出现在 WPF TreeView 中?
【发布时间】:2010-02-23 22:05:05
【问题描述】:

我必须在以下代码中更改什么以使“A Child Section”节点显示为First Section的子节点> 和第二部分

以下代码给了我一个 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>

代码背后:

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;
        }
    }

}

【问题讨论】:

    标签: c# wpf binding treeview observablecollection


    【解决方案1】:

    您似乎需要HierarchicalDataTemplate。他们在文章中有一个例子......

    【讨论】:

    • 谢谢,我根据这篇文章bea.stollnitz.com/blog/?p=18 获得的信息添加了 HierarchicalDataTemplate,但它仍然给了我相同的结果(上面的代码已更改)
    • 我明白了。将 ChildSection 转换为 ObservableCollection 并将 HierarchicalDataTemplate.ItemsSource 绑定到它。它会有帮助吗?
    • 我对上面的代码进行了这些更改,但现在它给了我一个 XamlParseException,好像 ChildSection 在某些部分上为空,但它们似乎都已初始化。
    • 是的,看起来您在添加任何内容之前忘记初始化 Section.ChildSections 集合...
    • 太好了,我只需要将 ChildSections 转换为完整的 INotifyPropertyChanged 属性,它就可以工作,感谢您的帮助!
    【解决方案2】:

    看看这个question 和接受的答案。它也应该为您指明正确的方向。

    基本思想是使用 ItemsSource 属性定义 HierarchicalDataTemplates 并使其按类型匹配。

    在你的情况下:

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

    编辑: 在您的代码中,您应该在向其添加值之前创建一个新集合:

    // The new was missing and resulted in the end in your XAML Parse Exception
    section.ChildSections = new ObservableCollection<Section>();
    section.ChildSections.Add( /*... */);
    

    【讨论】:

    • 我会看看,同时我做了你的改变并发布在上面,但它仍然给我一个 XamlParseException 说“一个对象没有被实例化”。
    • 我看了一下那个例子,其实我只需要一个类型:Sections under Sections under Sections。那么是否还需要定义类型呢,我认为 x:key 足以连接 TreeView 和 HierarchicalDataTemplate。
    • 是的,在这种情况下 x:Key 就足够了。但是,如果树中有异构节点,x:Key 将不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    相关资源
    最近更新 更多