代码之家  ›  专栏  ›  技术社区  ›  Andrei Rînea

HierarchicalDataTemplate中的DataTemplate

  •  2
  • Andrei Rînea  · 技术社区  · 15 年前

    <UserControl x:Class="WpfApplication4.TreeViewEx"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 x:Name="root">
        <Grid>
            <TreeView ItemsSource="{Binding Path=ItemsSource, ElementName=root}">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Node : "/>
                            <ContentControl Content="{Binding Path=AdditionalContent, ElementName=root}"/>
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </Grid>
    </UserControl>
    

    其思想是拥有ItemTemplate内容的固定部分和可定制部分。

    当然,我在TreeViewEx类上创建了两个依赖属性:

    public partial class TreeViewEx
    {
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
            "ItemsSource", typeof(IEnumerable), typeof(TreeViewEx));
    
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
    
        public static readonly DependencyProperty AdditionalContentProperty = DependencyProperty.Register(
            "AdditionalContent", typeof(object), typeof(TreeViewEx));
    
        public object AdditionalContent
        {
            get { return GetValue(AdditionalContentProperty); }
            set { SetValue(AdditionalContentProperty, value); }
        }
    
        public TreeViewEx()
        {
            InitializeComponent();
        }
    }
    

    有这样一个简单的节点类:

    public class Node
    {
        public string Name { get; set; }
        public int Size { get; set; }
        public IEnumerable<Node> Children { get; set; }
    }
    

    我会喂树景。我将TreeViewEx的一个实例放在WPF测试项目的主窗口上:

    <Window x:Class="WpfApplication4.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"
            xmlns:local="clr-namespace:WpfApplication4">
        <Grid>
            <local:TreeViewEx x:Name="tree">
                <local:TreeViewEx.AdditionalContent>
                    <TextBlock Text="{Binding Name}"/>
                </local:TreeViewEx.AdditionalContent>
            </local:TreeViewEx>
        </Grid>
    </Window>
    

    最后喂它:

    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
    
            var dummyData = new ObservableCollection<Node>
            {
                new Node
                {
                    Name = "Root", 
                    Size = 3,
                    Children = new ObservableCollection<Node>
                    {
                        new Node{
                            Name="Child1",
                            Size=2,
                            Children = new ObservableCollection<Node>{
                                new Node{
                                    Name = "Subchild", 
                                    Size = 1
                                }
    
                            }
                        }
    
                    }
                }
            };
    
            tree.ItemsSource = dummyData;
        }
    }
    

    我真的不明白。。我应该使用 数据模板 或者别的什么?

    1 回复  |  直到 15 年前
        1
  •  2
  •   Quartermeister    15 年前

    问题是您正在将内容设置为控件的实例,而该控件只能有一个父控件。展开树并将其添加到第二个节点时,它会将其从第一个节点中移除。

    正如您所怀疑的,您希望向TreeViewEx提供一个DataTemplate,而不是一个控件。可以使用ContentPresenter在树的每个级别实例化模板:

    将AdditionalContentProperty替换为:

    public static readonly DependencyProperty AdditionalContentTemplateProperty = DependencyProperty.Register(
        "AdditionalContentTemplate", typeof(DataTemplate), typeof(TreeViewEx));
    
    public DataTemplate AdditionalContentTemplate
    {
        get { return (DataTemplate)GetValue(AdditionalContentTemplateProperty); }
        set { SetValue(AdditionalContentTemplateProperty, value); }
    }
    

    将UserControl的XAML中的HierarchicalDataTemplate更改为:

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Node : "/>
        <ContentPresenter ContentTemplate="{Binding Path=AdditionalContentTemplate, ElementName=root}"/>
    </StackPanel>
    

    <local:TreeViewEx x:Name="tree">
        <local:TreeViewEx.AdditionalContentTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </local:TreeViewEx.AdditionalContentTemplate>
    </local:TreeViewEx>
    
    推荐文章