wpf - 在代码中添加项目时将 ItemTemplate 用于 TreeView

标签 wpf xaml treeview datatemplate itemtemplate

我正在后面的代码中手动添加 TreeViewItems,并想使用 DataTemplate 来显示它们,但不知道如何操作。我希望做这样的事情,但项目显示为空标题。我究竟做错了什么?

XAML

<Window x:Class="TreeTest.WindowTree"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowTree" Height="300" Width="300">
    <Grid>
        <TreeView Name="_treeView">
            <TreeView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Name}" />
                        <TextBlock Text="{Binding Path=Age}" />
                    </StackPanel>
                </DataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

背后的代码
using System.Windows;
using System.Windows.Controls;

namespace TreeTest
{
    public partial class WindowTree : Window
    {
        public WindowTree()
        {
            InitializeComponent();

            TreeViewItem itemBob = new TreeViewItem();
            itemBob.DataContext = new Person() { Name = "Bob", Age = 34 };

            TreeViewItem itemSally = new TreeViewItem();
            itemSally.DataContext = new Person() { Name = "Sally", Age = 28 }; ;

            TreeViewItem itemJoe = new TreeViewItem();
            itemJoe.DataContext = new Person() { Name = "Joe", Age = 15 }; ;
            itemSally.Items.Add(itemJoe);

            _treeView.Items.Add(itemBob);
            _treeView.Items.Add(itemSally);
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

最佳答案

您的 ItemTemplate 试图在 TextBlocks 中呈现“Name”和“Age”属性,但 TreeViewItem 没有“Age”属性并且您没有设置其“Name”。

因为您使用的是 ItemTemplate,所以无需将 TreeViewItems 添加到树中。相反,直接添加您的 Person 实例:

_treeView.Items.Add(new Person { Name = "Sally", Age = 28});

当然,问题在于您的底层对象(“Person”)没有任何层次结构概念,因此没有简单的方法可以将“Joe”添加到“Sally”。有几个更复杂的选项:

您可以尝试处理 TreeView.ItemContainerGenerator.StatusChanged 事件并等待生成“Sally”项目,然后获取它的句柄并直接添加 Joe:
public Window1()
{
    InitializeComponent(); 
    var bob = new Person { Name = "Bob", Age = 34 }; 
    var sally = new Person { Name = "Sally", Age = 28 }; 

    _treeView.Items.Add(bob); 
    _treeView.Items.Add(sally);

    _treeView.ItemContainerGenerator.StatusChanged += (sender, e) =>
    {
        if (_treeView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) 
            return;

        var sallyItem = _treeView.ItemContainerGenerator.ContainerFromItem(sally) as TreeViewItem;
        sallyItem.Items.Add(new Person { Name = "Joe", Age = 15 });
    };
}

或者,更好的解决方案是,您可以将层次结构概念引入到“人”对象中,并使用 HierarchicalDataTemplate 来定义 TreeView 层次结构:

XAML:
<Window x:Class="TreeTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowTree" Height="300" Width="300">
    <Grid>
        <TreeView Name="_treeView">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Subordinates}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Name}" />
                        <TextBlock Text="{Binding Path=Age}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

代码:
using System.Collections.Generic;
using System.Windows;

namespace TreeTest
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent(); 
            var bob = new Person { Name = "Bob", Age = 34 }; 
            var sally = new Person { Name = "Sally", Age = 28 }; 

            _treeView.Items.Add(bob); 
            _treeView.Items.Add(sally);
            sally.Subordinates.Add(new Person { Name = "Joe", Age = 15 });
        }

    }
    public class Person 
    {
        public Person()
        {
            Subordinates = new List<Person>();
        }

        public string Name { get; set; } 
        public int Age { get; set; }
        public List<Person> Subordinates { get; private set;  }
    }
}

这是一种更“面向数据”的方式来显示您的层次结构和更好的方法恕我直言。

关于wpf - 在代码中添加项目时将 ItemTemplate 用于 TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1175039/

相关文章:

c# - 如何将属性绑定(bind)到 xaml 中的属性值

wpf - 不应用 ContentPresenter 中的样式

c# - 在 WPF 中从一个 xaml 导航到另一个

xaml - 在 Windows Phone 8.1 应用程序中使用 Segoe WP Light

c# - 在 XAML 中向 DataGrid 添加行详细信息

wpf - 如何让 DataTemplate.DataTrigger 检查大于或小于?

wpf - 如何在 WPF 中的按钮内容中为单个字符添加下划线?

excel - 使用列标题和子标题填充 TreeView

java - 禁用 JavaFX 中的所有父节点,同时保持其所有子节点可点击

java - SWT 树 getItems()