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

如何在C# DataGridView列中添加TextBox、CheckBox等多种控件?

在DataGridView同一列中混合使用多种控件(TextBox/CheckBox/ComboBox)

要实现DataGridView同一列里显示不同类型的控件,核心思路是用自定义数据对象存储值和对应控件类型,再通过DataGridView的事件动态切换编辑控件、渲染显示内容。

步骤1:定义存储单元格数据的自定义类

这个类用来保存单元格的值、要使用的控件类型,以及ComboBox需要的选项:

public class GridCellData
{
    // 单元格的值
    public object Value { get; set; }
    // 要使用的控件类型(typeof(TextBox)/typeof(CheckBox)等)
    public Type ControlType { get; set; }
    // ComboBox的可选选项(按需添加)
    public List<object> Options { get; set; }
}

步骤2:构建数据源并绑定

把DataTable的第二列类型设为自定义的GridCellData,然后添加对应行数据:

// 初始化DataTable
DataTable dt = new DataTable();
dt.Columns.Add("Config Options", typeof(string));
// 第二列用自定义类类型
dt.Columns.Add(ModelIerarhic.SelectedNode.Parent.Name, typeof(GridCellData));

// 添加不同控件类型的行
// TextBox类型
dt.Rows.Add("文本输入项", new GridCellData { Value = "初始文本", ControlType = typeof(TextBox) });
// CheckBox类型
dt.Rows.Add("勾选选项", new GridCellData { Value = false, ControlType = typeof(CheckBox) });
// ComboBox类型(带选项)
dt.Rows.Add("下拉选择项", new GridCellData 
{ 
    Value = "选项2", 
    ControlType = typeof(ComboBox), 
    Options = new List<object> { "选项1", "选项2", "选项3" } 
});

// 绑定到DataGridView
dataGridView1.DataSource = dt;
// 设置编辑模式为进入单元格即编辑(可选,按需调整)
dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;

步骤3:绑定DataGridView事件处理控件切换和值同步

需要处理三个关键事件:CellFormatting(渲染显示内容)、CellBeginEdit(创建编辑控件)、CellEndEdit(保存编辑后的值)。

在窗体的构造函数或Load事件中绑定事件:

dataGridView1.CellFormatting += DataGridView1_CellFormatting;
dataGridView1.CellBeginEdit += DataGridView1_CellBeginEdit;
dataGridView1.CellEndEdit += DataGridView1_CellEndEdit;

然后实现事件逻辑:

1. CellFormatting:渲染单元格显示内容

private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    // 只处理第二列(索引为1,根据实际列索引调整)
    if (e.ColumnIndex == 1 && e.RowIndex >= 0)
    {
        var cellData = e.Value as GridCellData;
        if (cellData == null) return;

        // 根据控件类型渲染对应内容
        if (cellData.ControlType == typeof(CheckBox))
        {
            e.Value = cellData.Value;
            e.FormattingApplied = true;
        }
        else
        {
            e.Value = cellData.Value?.ToString() ?? string.Empty;
            e.FormattingApplied = true;
        }
    }
}

2. CellBeginEdit:创建对应编辑控件

private void DataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    if (e.ColumnIndex == 1 && e.RowIndex >= 0)
    {
        var dgv = sender as DataGridView;
        var cell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
        var cellData = cell.Value as GridCellData;
        if (cellData == null) return;

        // 清空单元格现有控件
        cell.Controls.Clear();

        Control editControl = null;
        // 根据控件类型创建对应编辑控件
        switch (cellData.ControlType.Name)
        {
            case nameof(TextBox):
                editControl = new TextBox();
                ((TextBox)editControl).Text = cellData.Value?.ToString() ?? string.Empty;
                break;
            case nameof(CheckBox):
                editControl = new CheckBox();
                ((CheckBox)editControl).Checked = (bool)(cellData.Value ?? false);
                ((CheckBox)editControl).Text = string.Empty; // 隐藏文本,只显示勾选框
                ((CheckBox)editControl).Alignment = ContentAlignment.MiddleCenter;
                break;
            case nameof(ComboBox):
                editControl = new ComboBox();
                var combo = (ComboBox)editControl;
                combo.DropDownStyle = ComboBoxStyle.DropDownList;
                // 添加下拉选项(如果有)
                if (cellData.Options != null)
                {
                    combo.Items.AddRange(cellData.Options.ToArray());
                }
                combo.SelectedItem = cellData.Value;
                break;
        }

        if (editControl != null)
        {
            editControl.Dock = DockStyle.Fill;
            cell.Controls.Add(editControl);
            editControl.Focus();
        }
    }
}

3. CellEndEdit:保存编辑后的值

private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == 1 && e.RowIndex >= 0)
    {
        var dgv = sender as DataGridView;
        var cell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
        var cellData = cell.Value as GridCellData;
        if (cellData == null || cell.Controls.Count == 0) return;

        var editControl = cell.Controls[0];
        // 根据控件类型获取编辑后的值
        switch (editControl.GetType().Name)
        {
            case nameof(TextBox):
                cellData.Value = ((TextBox)editControl).Text;
                break;
            case nameof(CheckBox):
                cellData.Value = ((CheckBox)editControl).Checked;
                break;
            case nameof(ComboBox):
                cellData.Value = ((ComboBox)editControl).SelectedItem;
                break;
        }

        // 更新单元格显示并移除控件
        cell.Value = cellData;
        dgv.InvalidateCell(cell);
        cell.Controls.Clear();
    }
}

补充说明

  • 如果需要支持更多控件类型,只需在switch分支中添加对应控件的创建逻辑即可。
  • 若不需要ComboBox的选项,可以去掉Options属性,简化自定义类。
  • 之前你尝试用bool类型生成CheckBox但无法插入值,是因为默认DataGridView绑定bool列时,值是直接绑定到数据源的,用上述自定义类的方式可以灵活控制值的存储和读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:54:18