You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF多级数据网格实现:如何从后台代码绑定子数据网格?

嘿,我来帮你搞定WPF里的多级嵌套DataGrid(带展开/折叠),还有后台代码绑定子网格的完整方案~

实现WPF多级嵌套DataGrid(带展开/折叠)

1. 先完善你的XAML结构

你之前写的主DataGrid列已经有了,现在要把RowDetailsTemplate里的子DataGrid绑定到正确的子集合,还可以加个展开/折叠按钮让交互更直观:

<DataGrid x:Name="MainJobsDataGrid" 
          AutoGenerateColumns="False"
          RowDetailsVisibilityMode="Collapsed"> <!-- 默认折叠子网格 -->
    <DataGrid.Columns>
        <!-- 自定义展开/折叠按钮列 -->
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button x:Name="ExpandCollapseBtn" 
                            Content="+" 
                            Click="ExpandCollapseBtn_Click"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Job Name" Binding="{Binding JobName}" />
        <DataGridTextColumn Header="Job Number" Binding="{Binding JobNumber}" />
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <!-- 子DataGrid要绑定到当前Job对象的Employees集合,别直接写{Binding}哦 -->
            <DataGrid x:Name="EmployeesDataGrid" 
                      ItemsSource="{Binding Employees}"
                      AutoGenerateColumns="False"
                      Margin="20,0,0,0"> <!-- 缩进一下,层级更清晰 -->
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Employee Name" Binding="{Binding Name}" />
                    <DataGridTextColumn Header="Position" Binding="{Binding Position}" />
                    <DataGridTextColumn Header="Employee ID" Binding="{Binding EmployeeId}" />
                </DataGrid.Columns>
            </DataGrid>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

2. 先定义好数据模型

后台需要先建两个类:一个是主数据(Job),一个是子数据(Employee),用ObservableCollection的话,数据变化时UI会自动更新,很方便:

// 子数据模型:员工信息
public class Employee
{
    public string Name { get; set; }
    public string Position { get; set; }
    public int EmployeeId { get; set; }
}

// 主数据模型:工作信息,包含下属的员工集合
public class Job
{
    public string JobName { get; set; }
    public string JobNumber { get; set; }
    // 这里就是子DataGrid要绑定的集合
    public ObservableCollection<Employee> Employees { get; set; } = new ObservableCollection<Employee>();
}

3. 后台代码绑定数据源

在窗口的加载事件或者构造函数里,构造好数据,直接绑定给主DataGrid就行:

public MainWindow()
{
    InitializeComponent();
    Loaded += MainWindow_Loaded;
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    // 先造点模拟数据,实际项目里你可以从数据库/接口拿
    var jobList = new ObservableCollection<Job>
    {
        new Job
        {
            JobName = "电商平台开发",
            JobNumber = "JOB-2024-001",
            Employees = 
            {
                new Employee { Name = "张三", Position = "后端开发", EmployeeId = 1001 },
                new Employee { Name = "李四", Position = "前端开发", EmployeeId = 1002 }
            }
        },
        new Job
        {
            JobName = "APP测试",
            JobNumber = "JOB-2024-002",
            Employees = 
            {
                new Employee { Name = "王五", Position = "功能测试", EmployeeId = 2001 },
                new Employee { Name = "赵六", Position = "性能测试", EmployeeId = 2002 }
            }
        }
    };

    // 把数据绑定给主DataGrid
    MainJobsDataGrid.ItemsSource = jobList;
}

4. 给展开/折叠按钮加逻辑

如果用了自定义的按钮,后台写个点击事件,切换行详情的可见性就行:

private void ExpandCollapseBtn_Click(object sender, RoutedEventArgs e)
{
    var btn = sender as Button;
    var currentJob = btn.DataContext as Job;
    var targetRow = MainJobsDataGrid.ItemContainerGenerator.ContainerFromItem(currentJob) as DataGridRow;

    if (targetRow != null)
    {
        // 切换可见性
        targetRow.DetailsVisibility = targetRow.DetailsVisibility == Visibility.Visible 
            ? Visibility.Collapsed 
            : Visibility.Visible;
        // 按钮文本跟着变
        btn.Content = targetRow.DetailsVisibility == Visibility.Visible ? "-" : "+";
    }
}

几个小提醒

  • 子DataGrid的ItemsSource一定要绑定到主数据对象的子集合(比如示例里的{Binding Employees}),之前你写的{Binding}会绑定到Job对象本身,肯定出不来数据哦。
  • 如果需要动态增删数据,一定要用ObservableCollection,普通List的话UI不会自动更新。
  • 要是不想用自定义按钮,也可以把主DataGrid的RowDetailsVisibilityMode设为VisibleWhenSelected,选中行就自动展开子网格。

内容的提问来源于stack exchange,提问作者Cricket Infatuation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:18:20