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

WPF DataGrid如何通过代码绑定类中列表动态添加班次列?

解决WPF DataGrid动态绑定班次列的方案

嘿,这个动态生成DataGrid班次列的需求我熟,给你一步步讲怎么实现!

1. 优化Employee类(可选但推荐)

为了让数据变化能实时同步到UI,最好让Employee实现INotifyPropertyChanged接口;如果后续需要支持班次数量动态更新,也可以把List<int>换成ObservableCollection<int>:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.Generic;

public class Employee : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }

    private string _surName;
    public string SurName
    {
        get => _surName;
        set { _surName = value; OnPropertyChanged(); }
    }

    private int _rest;
    public int Rest
    {
        get => _rest;
        set { _rest = value; OnPropertyChanged(); }
    }

    private int _worked;
    public int Worked
    {
        get => _worked;
        set { _worked = value; OnPropertyChanged(); }
    }

    private List<int> _perShift = new List<int>();
    public List<int> PerShift
    {
        get => _perShift;
        set { _perShift = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 动态生成DataGrid列的核心逻辑

在窗口加载完成后(或者ViewModel初始化时),我们需要先确定班次的总数量,再生成对应列并绑定到PerShift的索引位置。这里有两种确定班次数量的方式:

  • 方式一:取所有员工PerShift列表的最大长度(适合没有单独班次表的场景)
  • 方式二:直接从数据库查询总班次数量(更准确,适合有班次管理表的场景)

下面是方式一的代码示例(假设你已经有了填充好数据的员工集合):

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // 模拟从数据库获取的员工数据
    var employeeCollection = new ObservableCollection<Employee>
    {
        new Employee { Name = "张三", Worked = 22, Rest = 8, PerShift = new List<int> { 5, 6, 4 } },
        new Employee { Name = "李四", Worked = 20, Rest = 10, PerShift = new List<int> { 3, 7 } }
    };

    // 计算需要生成的班次列数量:取所有员工PerShift的最大长度
    int maxShiftCount = employeeCollection.Max(emp => emp.PerShift.Count);

    // 先添加固定列:姓名、总出勤、休息天数
    dataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = "姓名",
        Binding = new Binding("Name")
    });

    dataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = "总出勤天数",
        Binding = new Binding("Worked")
    });

    dataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = "休息天数",
        Binding = new Binding("Rest")
    });

    // 动态生成班次列
    for (int i = 0; i < maxShiftCount; i++)
    {
        // 必须单独捕获循环变量,避免闭包导致所有列绑定到最后一个索引
        int currentShiftIndex = i;
        dataGrid.Columns.Add(new DataGridTextColumn
        {
            Header = $"第{currentShiftIndex + 1}班",
            // 绑定到PerShift的对应索引,FallbackValue确保无数据时显示0
            Binding = new Binding($"PerShift[{currentShiftIndex}]")
            {
                FallbackValue = 0,
                TargetNullValue = 0
            }
        });
    }

    // 设置DataGrid的数据源
    dataGrid.ItemsSource = employeeCollection;
}

3. 关键注意点

  • 闭包陷阱:循环里一定要把i赋值给局部变量currentShiftIndex,不然所有动态列都会绑定到最后一个索引值,这是WPF开发里很容易踩的坑。
  • 空值处理:通过FallbackValue和TargetNullValue设置默认值,避免某个员工没有该班次记录时UI显示空白。
  • 数据同步:因为我们实现了INotifyPropertyChanged,后续员工的班次数据发生变化时,UI会自动同步更新。

如果你的数据库里有单独的班次表,直接用班次表的记录数来生成列会更准确,只需要把maxShiftCount替换成从数据库查询到的总班次数量即可。

内容的提问来源于stack exchange,提问作者Axilleas Kar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:30:47