【问题标题】:Binding custom object consisting of different List<T> to a TreeView将由不同 List<T> 组成的自定义对象绑定到 TreeView
【发布时间】:2014-06-10 05:53:06
【问题描述】:

我想将我的 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; }
    }

节点属性

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>

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

【问题讨论】:

    标签: c# .net wpf treeview


    【解决方案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>
    

    您可以尝试两种方法,然后选择最适合您需求的方法

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-10
        相关资源
        最近更新 更多