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

如何将嵌套列表绑定到DataGrid并实现动态列与复选框列

WPF DataGrid动态绑定嵌套列表并实现复选框命令绑定

需求说明

需要将ViewModel中的嵌套列表结构绑定到DataGrid,实现以下效果:

  • 动态展示ValuesColumns中的数据列,支持列的动态增删
  • IsCheckedColumn显示复选框而非文本,绑定ViewModel的ICommand并传递当前Row对象作为参数

ViewModel代码

public class ParametersDataGridViewModel : ViewModelBase
{
    public ObservableCollection<Row> RowsList { get; set; } = new();
    // 用于复选框绑定的命令
    public ICommand CheckBoxCommand { get; set; }
}

public class Row
{
    public string NameColumn { get; set; }
    public bool IsCheckedColumn { get; set; }
    public ObservableCollection<Values> ValuesColumns { get; set; } = new();
}

public class Values
{
    public string ValueName { get; set; }
    public List<string> ValueValue { get; set; }
}

实现方案

1. 动态生成DataGrid列

由于ValuesColumns是动态集合,需在代码中监听集合变化并生成对应列,可在View的后台代码中处理:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // 添加固定名称列
    dataGrid.Columns.Add(new DataGridTextColumn
    {
        Header = "名称",
        Binding = new Binding("NameColumn")
    });

    // 添加复选框列
    var checkBoxColumn = new DataGridTemplateColumn
    {
        Header = "选择"
    };
    var checkBoxFactory = new FrameworkElementFactory(typeof(CheckBox));
    // 绑定复选框选中状态到Row的IsCheckedColumn
    checkBoxFactory.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsCheckedColumn") { Mode = TwoWay });
    // 绑定ViewModel的命令,传递当前Row作为参数
    checkBoxFactory.SetBinding(CheckBox.CommandProperty, new Binding("DataContext.CheckBoxCommand") 
    { 
        RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGrid), 1) 
    });
    checkBoxFactory.SetBinding(CheckBox.CommandParameterProperty, new Binding());
    checkBoxColumn.CellTemplate.VisualTree = checkBoxFactory;
    dataGrid.Columns.Add(checkBoxColumn);

    // 初始化动态列并监听集合变化
    if (DataContext is ParametersDataGridViewModel vm && vm.RowsList.Any())
    {
        // 以第一行的ValuesColumns为初始列(若各行列结构不同,需额外处理)
        foreach (var value in vm.RowsList.First().ValuesColumns)
        {
            AddDynamicColumn(value.ValueName);
        }

        // 监听每一行ValuesColumns的增删操作,同步更新列
        foreach (var row in vm.RowsList)
        {
            row.ValuesColumns.CollectionChanged += ValuesColumns_CollectionChanged;
        }
    }
}

private void ValuesColumns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        foreach (Values newVal in e.NewItems)
        {
            AddDynamicColumn(newVal.ValueName);
        }
    }
    else if (e.Action == NotifyCollectionChangedAction.Remove)
    {
        foreach (Values removedVal in e.OldItems)
        {
            var targetColumn = dataGrid.Columns.FirstOrDefault(c => c.Header.ToString() == removedVal.ValueName);
            if (targetColumn != null)
            {
                dataGrid.Columns.Remove(targetColumn);
            }
        }
    }
}

private void AddDynamicColumn(string columnName)
{
    // 避免重复添加列
    if (dataGrid.Columns.Any(c => c.Header.ToString() == columnName))
        return;

    var dynamicColumn = new DataGridTextColumn
    {
        Header = columnName,
        // 绑定到对应列的ValueValue(此处取第一个元素,可根据需求调整)
        Binding = new Binding($"ValuesColumns[{dataGrid.Columns.Count - 2}].ValueValue[0]")
    };
    dataGrid.Columns.Add(dynamicColumn);
}

2. XAML基础配置

在XAML中设置DataGrid的数据源绑定:

<DataGrid x:Name="dataGrid" 
          ItemsSource="{Binding RowsList}" 
          AutoGenerateColumns="False"
          Loaded="Window_Loaded"/>

注意事项

  • 若各行ValuesColumns的列结构不一致(数量/名称不同),需额外处理列的统一显示逻辑,比如使用DataTemplateSelector
  • 确保ViewModel中的CheckBoxCommand已正确实现(例如使用RelayCommand)
  • 需监听RowsList的CollectionChanged事件,对新增的Row也要绑定ValuesColumns的变化监听

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:20:29