This link will show you how:
DataGrid with row details - The complete WPF tutorial[
^]
Here is a little demo with Order > Product grouped data structure:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MockData();
MyDataGrid.ItemsSource = CustomerOrders;
}
private Random random = new();
private List<Product> products = new();
private List<Order> Orders = new();
private List<CustomerOrder> CustomerOrders = new();
private void MockData()
{
for (int i = 0; i < 10; i++)
{
Orders.Add(new Order(
i,
DateTime.Now - TimeSpan.FromDays(random.Next(1, 500))));
}
for (int i = 0; i < 100; i++)
{
products.Add(new(
i,
$"Product {i}",
random.Next(20, 100),
random.Next(1, 5),
Orders[random.Next(0, 9)].Id));
}
foreach (Order order in Orders)
{
List<Product> orderProducts = products
.Where(p => p.OrderId == order.Id)
.ToList();
order.TotalCost = orderProducts
.Select(p => p.Cost)
.Sum();
CustomerOrders.Add(new (order, orderProducts));
}
}
}
public record Product(int Id, string Name, float Cost, int Quantity, int OrderId);
public record Order(int Id, DateTime Created) { public float TotalCost { get; set; } }
public record CustomerOrder(Order Order, List<Product> Products);
Now the UI:
<Window x:Class="WpfDataGridParentChild.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Wpf DataGrid Parent Child" Height="450" Width="800">
<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False" RowDetailsVisibilityMode="Visible">
<DataGrid.Columns>
<DataGridTextColumn Header="ORDER ID" Binding="{Binding Order.Id}" />
<DataGridTextColumn Header="ORDER Date" Binding="{Binding Order.Created}" />
<DataGridTextColumn Header="TOTAL COST" Binding="{Binding Order.TotalCost}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Products}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="PRODUCT ID" Binding="{Binding Id}" />
<DataGridTextColumn Header="NAME" Binding="{Binding Name}" />
<DataGridTextColumn Header="QTY" Binding="{Binding Quantity}" />
<DataGridTextColumn Header="COST" Binding="{Binding Cost}" />
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Window>
I have all orders expanded with products per order.