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

WPF动态生成DataGrid/ListView展示类表格嵌套数据方案

问题根因

你当前代码所有单元格显示(Collection)是两个问题导致的:

  • 列绑定直接指向Values这个List<ClassB>集合属性,DataGrid默认会直接输出集合类型的默认字符串标识,不会自动取集合内的元素做匹配
  • 你的数据结构是按列维度存储的(每个ClassA对应一列,内部Values存该列所有行的值),但DataGrid默认按行维度绑定数据源,你既没有给DataGrid指定行级数据源,也没有在绑定里指定当前行对应的元素索引,自然无法正确匹配值。
实现方案

核心思路是先对齐行维度,再通过多绑定传入ViewModel实例和当前行索引,按列索引+行索引定位到具体的DisplayValue,同时处理索引越界(无值留空)的场景。

第一步:添加两个必要的值转换器

// 行号转换器:把从0开始的行索引转成从1开始显示的行号
public class RowIndexToNumberConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is int rowIndex ? rowIndex + 1 : Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

// 单元格值转换器:按列索引、行索引定位具体值,无值返回空字符串
public class GridCellValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length < 2 || parameter is not int colIndex) 
            return string.Empty;
        
        if (values[0] is ViewModelClass vm && values[1] is int rowIndex)
        {
            // 各种越界场景直接返回空
            if (colIndex >= vm.Data.Count) return string.Empty;
            var targetColumn = vm.Data[colIndex];
            if (targetColumn.Values == null || rowIndex >= targetColumn.Values.Count) 
                return string.Empty;
            
            return targetColumn.Values[rowIndex].DisplayValue ?? string.Empty;
        }
        return string.Empty;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

第二步:替换你原来的动态生成列代码

var vm = DataContext as ViewModelClass;
if (vm == null || vm.Data == null || vm.Data.Count == 0) 
    return;

MyDataGrid.AutoGenerateColumns = false;
MyDataGrid.Columns.Clear();

// 计算总行数:取所有列中Values列表的最大长度
int totalRows = vm.Data.Max(col => col.Values?.Count ?? 0);
// 给DataGrid指定行数据源:就是0到totalRows-1的索引序列,对应每一行的序号
MyDataGrid.ItemsSource = Enumerable.Range(0, totalRows).ToList();

// 添加首列(行号列)
MyDataGrid.Columns.Add(new DataGridTextColumn
{
    Header = "Row",
    Binding = new Binding(".") { Converter = new RowIndexToNumberConverter() }
});

// 逐个添加数据列
for (int colIndex = 0; colIndex < vm.Data.Count; colIndex++)
{
    var columnData = vm.Data[colIndex];
    // 多绑定:第一个参数传ViewModel实例,第二个参数传当前行索引
    var cellBinding = new MultiBinding
    {
        Converter = new GridCellValueConverter(),
        ConverterParameter = colIndex
    };
    cellBinding.Bindings.Add(new Binding(".") { Source = vm });
    cellBinding.Bindings.Add(new Binding("."));

    MyDataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = columnData.ColumnName,
        Binding = cellBinding
    });
}

效果说明

运行后会完全匹配你给出的表格效果:

  • 首列显示从1开始的行号
  • 后续列头对应每个ClassA的ColumnName
  • 单元格按行、列索引匹配对应ClassB的DisplayValue,无匹配值时自动留空
  • 不需要修改你现有的实体类定义,也不需要额外做数据结构转置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:24:41