将包含不同List <t>的自定义对象绑定到TreeView </t>

时间:2014-06-10 05:53:07

标签: c# .net wpf treeview

我想将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。

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

我想以不同的方式设置Child和属性的样式。

2 个答案:

答案 0 :(得分:1)

你需要一个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>

您可以尝试两者并选择最适合您需求的产品

答案 1 :(得分:1)

您必须使用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>