如何在wpf应用程序中使gridview成为树视图的子元素

时间:2009-09-06 10:37:56

标签: wpf datagrid treeview

我正在尝试从数据库中填充数据网格(或gridview)作为树视图的子元素。我能够从树中的数据库中获取数据,但是,它似乎不适用于数据网格。这是我的xaml代码:

<Window x:Class="AttemptUsingHirarchichalData.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:data="clr-namespace:AttemptUsingHirarchichalData"
    xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
    Title="Window1" Height="300" Width="300">
<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type data:Root}"
                              ItemsSource="{Binding Path=RootList}">
        <TextBlock Text="{Binding RootNode}"/>

    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type data:Nodes}"
                              ItemsSource="{Binding Path=ChildList}">

        <TextBlock Text="{Binding ChildNode}"/>
    </HierarchicalDataTemplate>
</Window.Resources>

<Grid>
    <TreeView Name="TreeView1">
        <TreeViewItem ItemsSource="{Binding Path=RootList}"
                      Header="{Binding RootNode}"/>
        <TreeViewItem ItemsSource="{Binding Path=dt_Age}"
                      Header="{Binding dt_Age}"/>
    </TreeView>

</Grid>

我的代码隐藏是这样的:

InitializeComponent();

Root obj_Root = new Root();
obj_Root.RootNode = "RootNode";
obj_Root.RootList = new List<Nodes>();

Class1 obj_Class1 = new Class1();
DataTable dt_Age = obj_Class1.GetAgeInComboBox();

for (int i = 0; i < dt_Age.Rows.Count; i++)
{
    Nodes obj_AgeNode = new Nodes();
    obj_AgeNode.ChildNode = dt_Age.Rows[i][0].ToString();
    obj_Root.RootList.Add(obj_AgeNode);

    Class1 obj_class = new Class1();
    DataTable dt_name = new DataTable();
    dt_name = obj_class.GetName(Convert.ToInt32(dt_Age.Rows[i][0]));
    obj_AgeNode.ChildList = new List<Nodes>();
    //gridv
    for (int j = 0; j < dt_name.Rows.Count; j++)
    {
        Nodes obj_NameNode = new Nodes();
        obj_NameNode.ChildNode = dt_name.Rows[j][0].ToString();
        obj_AgeNode.ChildList.Add(obj_NameNode);
    }
}

TreeView1.DataContext = obj_Root;

我的班级文件将此作为其中的一部分:

public class Nodes
{
    public string ChildNode { get; set; }
    public List<Nodes> ChildList { get; set; }
}

public class Root
{
    public string RootNode { get; set; }
    public List<Nodes> RootList { get; set; }
}

 public DataTable GetAgeInComboBox()
 {
     SqlDataAdapter da_Age = new SqlDataAdapter("select distinct Age from myfrstattemt", conn1);
     DataTable dt_Age = new DataTable();
     da_Age.Fill(dt_Age);
     return dt_Age;
 }

请告诉我如何实施它。我是新手,所以请原谅我的愚蠢错误,请尝试用简单的语言解释。谢谢。

这是我实际需要做的事情

2 个答案:

答案 0 :(得分:11)

好消息是,你在这里做的工作比你需要的多得多,这可能就是你遇到麻烦的原因。

坏消息是你应该更多地研究WPF,以便正确地理解这一点,并提出一个干净简洁的好方法。我会试着指出你正确的方向。

首先,你应该了解ItemsControl。它是一个非常强大的类,是WPF应用程序中使用的许多日常控件的基类。您应该了解如何将任何集合(IEnumerable,IList,IBindingList等)绑定到ItemsControl的ItemsSource属性将导致创建子项。

然后您应该了解(如果您还没有)数据类型如何通过DataTemplates转换为UI元素。这是一个简单而强大的概念。

然后你应该尝试上面的一个小扩展,即HeaderedItemsControl和HierarchicalDataTemplate。这将为您提供以您希望的方式使用TreeView所需的所有工具。

您无需在C#代码中创建任何TreeViewItems。如果您可以获取底层数据对象以反映您想要显示的层次结构(无论每个节点是一个简单的文本标签还是数据网格),那么您可以为所有级别创建分层数据模板,并让WPF负责绑定所有级别并为您创建TreeViewItems。

修改

我对您编辑过的问题有一些疑问:

  1. RootNodes之间的区别是什么?
  2. 您是否有一个类层次结构来模拟节点之间的关系?如果是这样,只需使用它而不是将对象复制到RootNodes的实例中。我会给你一个例子。
  3. 我们假设您有CustomerOrder个人,每个订单都有Item个。

    public class Customer
    {
        public string Name { get; set; }
        public IEnumerable<Order> Orders { get; set; }
    }
    
    public class Order
    {
        public DateTime PurchaseDate { get; set; }
        public IEnumerable<OrderItem> Items { get; set; }
    }
    
    public class OrderItem
    {
        public string ProductName { get; set; }
        public int Quantity { get; set; }
        public double UnitPrice { get; set; }
        public double TotalPrice { get; set; }
    }
    

    以上类型代表层次结构。如果您有这样的结构,那么您可以将它直接绑定到UI。您无需创建任何RootNode个对象。这是WPF的方式:)

    (请注意,如果您没有上述类层次结构,您可以设置专门创建一个用于UI。如果您有兴趣,请阅读有关MVVM模式的更多信息。)

    在您的XAML中,您将TreeView定义为:

    <TreeView x:Name="_treeView" ItemsSource="{Binding}">
      <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type data:Customer}"
                                  ItemsSource="{Binding Path=Orders}">
          <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type data:Order}">
          <StackPanel>
            <TextBlock Text="{Binding PurchaseDate}"/>
            <ListView ItemsSource="{Binding Items}">
              <ListView.View>
                <GridView>
                  <GridViewColumn DisplayMemberBinding="{Binding ProductName}" />
                  <GridViewColumn DisplayMemberBinding="{Binding Quantity}" />
                  <GridViewColumn DisplayMemberBinding="{Binding UnitPrice}" />
                  <GridViewColumn DisplayMemberBinding="{Binding TotalPrice}" />
                </GridView>
              </ListView.View>
            </ListView>
          </StackPanel>
        </DataTemplate>
      </TreeView.Resources>
    </TreeView>
    

    在代码隐藏中,你会做这样的事情:

     _treeView.DataContext = customers; // eg. IEnumerable<Customer>
    

答案 1 :(得分:0)

Marlon Grech可能值得一看this post