How to make gridview a child element of a treeview in wpf application

前端 未结 2 1098
粉色の甜心
粉色の甜心 2021-02-06 17:25

I am trying to populate a datagrid (or gridview) as a child elment of a treeview from the database. I am able to get data from the DB in the tree, however, it doesnt seem to wor

相关标签:
2条回答
  • 2021-02-06 17:35

    Might be worth having a look at this post by Marlon Grech.

    0 讨论(0)
  • 2021-02-06 17:37

    The good news is that you're doing a lot more work here than you need to, which is probably why you're having trouble.

    The bad news is that you should really study a little more about WPF to properly grok this and come up with a good approach that's clean and concise. I'll try and point you in the right direction.

    Firstly, you should get your head around ItemsControl. It's a really powerful class and is the base class of many of the everyday controls you would use in a WPF application. You should understand how binding any collection (IEnumerable, IList, IBindingList etc) to the ItemsSource property of ItemsControl will cause child items to be created.

    You should then understand (if you don't already) how data types are converted into UI elements via DataTemplates. This is a simple but powerful concept.

    Then you should experiment with a small extension to the above, namely HeaderedItemsControl and HierarchicalDataTemplate. This will give you all the tools you need to use the TreeView in the way you want to.

    At no point would you need to create any TreeViewItems in C# code. If you can get the underlying data objects to reflect the hierarchy you want to display (irrespective of whether each node is a simple text label or a data grid) then you can create hierarchical data templates for all levels and have WPF take care of binding everything and creating the TreeViewItems for you.

    EDIT

    I have some questions for your edited question:

    1. What is the difference between Root and Nodes?
    2. Do you have a class hierarchy that models the relationship between nodes? If so, just use that rather than copying the objects into instances of Root and Nodes. I'll give you a made up example.

    Let's assume you have Customers who place Orders, and each order has Items.

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

    The above types represent a hierarchy. If you have a structure like this, then you can bind it directly to the UI. You don't need to create any Root or Node objects. This is the WPF way :)

    (Note that if you don't have the above class hierarchy, you might set about creating one specifically for use in the UI. Read more about the MVVM pattern if you're interested.)

    In your XAML you would define the TreeView as:

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

    And in code-behind, you'd do something like this:

     _treeView.DataContext = customers; // eg. IEnumerable<Customer>
    
    0 讨论(0)
提交回复
热议问题