由不同的List到TreeView

本文关键字:TreeView List | 更新日期: 2023-09-27 18:07:46

我想将Node类的对象绑定到一个树视图。

节点类
public class Node
    {
        public string Text { get; set; }
        public List<Node> Child { get; set; }
        public List<NodeAttribute> Attributes { get; set; }
        public bool IsLeafNode { get; set; }
        public bool HasAttributes { get; set; }
    }

NodeAttribute

public class NodeAttribute
    {
        public string Attribute { get; set; }
        public string Value { get; set; }
    }

我可以使用HierarchicalDataTemplate显示Child,但不能使用Attributes。

<TreeView Name="tv" ItemsSource="{Binding Child}">
            <TreeView.Resources>
                <HierarchicalDataTemplate ItemsSource="{Binding Child}" DataType="{x:Type tvcc:Node}">
                    <StackPanel>
                        <TextBlock Text="{Binding Text}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>

我想样式的孩子和属性不同

由不同的List<T>到TreeView

您需要一个CompositeCollection来组合Child和Attributes,并将它们绑定到HierarchicalDataTemplate的ItemsSource

我为你准备了一个样品

在Node类中添加了CompositeCollection ChildAndAttributes

public class Node
{
    public Node()
    {
        Child = new List<Node>();
        Attributes = new List<NodeAttribute>();
    }
    public string Text { get; set; }
    public List<Node> Child { get; set; }
    public List<NodeAttribute> Attributes { get; set; }
    public bool IsLeafNode { get; set; }
    public bool HasAttributes { get; set; }
    CompositeCollection comp;
    public CompositeCollection ChildAndAttributes
    {
        get
        {
            if (comp == null)
            {
                comp = new CompositeCollection();
                comp.Add(new CollectionContainer() { Collection = Child });
                comp.Add(new CollectionContainer() { Collection = Attributes });
            }
            return comp;
        }
    }
}

如果需要,您可以调整组合集合使其首先具有属性,只需更改添加到集合

的顺序

XAML

    <TreeView Name="tv">
        <TreeView.Resources>
            <!--created seperate tempates for Node and NodeAttribute-->
            <DataTemplate DataType="{x:Type tvcc:Node}">
                <TextBlock Text="{Binding Text}"
                           Foreground="Navy" />
            </DataTemplate>
            <DataTemplate DataType="{x:Type tvcc:NodeAttribute}">
                <TextBlock Text="{Binding Attribute}"
                           Foreground="Crimson" />
            </DataTemplate>
        </TreeView.Resources>
        <!--moved your original template to Item Template or tree-->
        <TreeView.ItemTemplate>
            <!--binded ChildAndAttributes to ItemsSource-->
            <HierarchicalDataTemplate ItemsSource="{Binding ChildAndAttributes}">
                <!--this will pick up the data template for respective element-->
                <ContentControl Content="{Binding}" />
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <!--below is sample data-->
        <tvcc:Node Text="hello">
            <tvcc:Node.Attributes>
                <tvcc:NodeAttribute Attribute="attribute child" />
            </tvcc:Node.Attributes>
            <tvcc:Node.Child>
                <tvcc:Node Text="hello child">
                    <tvcc:Node.Attributes>
                        <tvcc:NodeAttribute Attribute="attribute child 1" />
                    </tvcc:Node.Attributes>
                </tvcc:Node>
            </tvcc:Node.Child>
        </tvcc:Node>
        <tvcc:Node Text="hello2">
            <tvcc:Node.Attributes>
                <tvcc:NodeAttribute Attribute="attribute child 2" />
            </tvcc:Node.Attributes>
            <tvcc:Node.Child>
                <tvcc:Node Text="hello child 2">
                    <tvcc:Node.Attributes>
                        <tvcc:NodeAttribute Attribute="attribute child 2" />
                    </tvcc:Node.Attributes>
                </tvcc:Node>
            </tvcc:Node.Child>
        </tvcc:Node>
    </TreeView>

您可以根据需要修改数据模板

替代方法

你也可以修改你现有的模板来达到类似的效果,而不用使用CompositCollections

<HierarchicalDataTemplate ItemsSource="{Binding Child}"
                            DataType="{x:Type tvcc:Node}">
    <StackPanel>
        <TextBlock Text="{Binding Text}"
                    Foreground="Navy" />
        <ItemsControl ItemsSource="{Binding Attributes}" Margin="10,0,0,0">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Attribute}"
                                Foreground="Crimson" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</HierarchicalDataTemplate>

你可以两者都试试,然后选择最适合你需要的

您将不得不使用CompositeCollection来解决您的问题。

下面是将节点转换为组合集合的转换器

public class CompositeNodeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var node = value as Node;
            CompositeCollection collection = new CompositeCollection();
            CollectionContainer container = new CollectionContainer();
            container.Collection = node.Child;
            collection.Add(container);
            container = new CollectionContainer();
            container.Collection = node.Attributes;
            collection.Add(container);
            return collection;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

然后你可以在xaml中将其绑定为:

  <TreeView Name="tv" ItemsSource="{Binding NodeCollection}">
        <TreeView.Resources>
            <controls:CompositeNodeConverter x:Key="CompositeNodeConverter"></controls:CompositeNodeConverter>
            <HierarchicalDataTemplate ItemsSource="{Binding Converter={StaticResource CompositeNodeConverter}}" DataType="{x:Type controls:Node}">
                <StackPanel>
                    <TextBlock Text="{Binding Text}"/>
                </StackPanel>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type controls:NodeAttribute}">
                <StackPanel>
                    <TextBlock Text="{Binding Value}"/>
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
相关文章: