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

如何在C# WinForms的DataGridView中实现单元格内滚动?

给DataGridView指定列的单元格添加滚动条(仅长内容时显示)

不需要重写整个DataGridView,只需通过自定义单元格/列或动态嵌入带滚动条的TextBox两种方案实现,以下是具体步骤:


方案一:自定义单元格与列(推荐,集成度高)

通过继承DataGridViewTextBoxCell和DataGridViewTextBoxColumn,创建支持滚动条的自定义单元格类型,仅对目标列使用该类型即可。

1. 定义自定义单元格和编辑控件

// 自定义支持滚动的文本单元格
public class DataGridViewScrollableTextBoxCell : DataGridViewTextBoxCell
{
    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
        var txtBox = DataGridView.EditingControl as TextBox;
        if (txtBox == null) return;

        txtBox.Multiline = true;
        txtBox.WordWrap = true;
        txtBox.BorderStyle = BorderStyle.None;
        // 根据内容高度判断是否显示垂直滚动条
        var textSize = TextRenderer.MeasureText(txtBox.Text, txtBox.Font, new Size(txtBox.Width, int.MaxValue), TextFormatFlags.WordBreak);
        txtBox.ScrollBars = textSize.Height > txtBox.Height ? ScrollBars.Vertical : ScrollBars.None;
    }

    public override Type EditType => typeof(DataGridViewScrollableTextBoxEditingControl);
}

// 自定义编辑控件,实现IDataGridViewEditingControl接口
public class DataGridViewScrollableTextBoxEditingControl : TextBox, IDataGridViewEditingControl
{
    private DataGridView _dgv;
    private bool _valueChanged;
    private int _rowIndex;

    public DataGridView EditingControlDataGridView
    {
        get => _dgv;
        set => _dgv = value;
    }

    public object EditingControlFormattedValue
    {
        get => Text;
        set => Text = value.ToString();
    }

    public int EditingControlRowIndex
    {
        get => _rowIndex;
        set => _rowIndex = value;
    }

    public bool EditingControlValueChanged
    {
        get => _valueChanged;
        set => _valueChanged = value;
    }

    public Cursor EditingPanelCursor => base.Cursor;
    public bool RepositionEditingControlOnValueChange => false;

    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle style)
    {
        Font = style.Font;
        ForeColor = style.ForeColor;
        BackColor = style.BackColor;
    }

    public bool EditingControlWantsInputKey(Keys keyData, bool dgvWantsKey)
    {
        // 优先让文本框处理方向键、编辑键等输入
        switch (keyData & Keys.KeyCode)
        {
            case Keys.Left: case Keys.Right: case Keys.Up: case Keys.Down:
            case Keys.Home: case Keys.End: case Keys.Delete: case Keys.Back:
                return true;
            default:
                return !dgvWantsKey;
        }
    }

    public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
    {
        return EditingControlFormattedValue;
    }

    public void PrepareEditingControlForEdit(bool selectAll)
    {
        if (selectAll) SelectAll();
        else SelectionStart = Text.Length;
    }
}

2. 定义自定义列

public class DataGridViewScrollableTextBoxColumn : DataGridViewTextBoxColumn
{
    public DataGridViewScrollableTextBoxColumn()
    {
        CellTemplate = new DataGridViewScrollableTextBoxCell();
    }
}

3. 在窗体中使用自定义列

方式一:设计时添加

打开窗体设计器,右键DataGridView → 编辑列,删除目标列后添加DataGridViewScrollableTextBoxColumn,设置列名、表头文本等属性。

方式二:代码动态添加

private void Form_Load(object sender, EventArgs e)
{
    // 移除目标列(示例为索引2的列)
    dataGridView1.Columns.RemoveAt(2);
    
    // 创建并添加自定义滚动列
    var scrollColumn = new DataGridViewScrollableTextBoxColumn
    {
        Name = "LongContentColumn",
        HeaderText = "长内容列",
        Width = 220
    };
    dataGridView1.Columns.Insert(2, scrollColumn);

    // 配置单元格换行与行高(可选:固定行高或自动调整)
    dataGridView1.RowsDefaultCellStyle.WrapMode = DataGridViewTriState.True;
    // 自动调整行高(若要固定行高,设置dataGridView1.RowTemplate.Height = 100;)
    dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

    // 添加测试数据
    dataGridView1.Rows.Add("测试项1", "测试项2", 
        "这是一段超长文本,包含多行内容,用来验证滚动条的显示逻辑。当文本高度超过单元格高度时,会自动启用垂直滚动条;内容较短时则隐藏滚动条。这是一段超长文本,包含多行内容,用来验证滚动条的显示逻辑。",
        "测试项4", "测试项5", "测试项6");
}

方案二:动态嵌入TextBox(快速实现)

无需自定义类,通过CellEnter/CellLeave事件动态在目标单元格中添加带滚动条的TextBox,离开单元格时将内容写回单元格。

实现代码

private TextBox _scrollTxtBox;

private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
    // 仅处理目标列(示例为索引2的列)
    if (e.ColumnIndex != 2 || e.RowIndex < 0) return;

    // 清理之前的TextBox
    _scrollTxtBox?.Dispose();
    _scrollTxtBox = null;

    // 获取单元格显示区域
    var cellRect = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);

    // 创建带滚动条的TextBox
    _scrollTxtBox = new TextBox
    {
        Multiline = true,
        WordWrap = true,
        BorderStyle = BorderStyle.None,
        Text = dataGridView1[e.ColumnIndex, e.RowIndex].Value?.ToString() ?? "",
        Font = dataGridView1.DefaultCellStyle.Font,
        ForeColor = dataGridView1.DefaultCellStyle.ForeColor,
        BackColor = dataGridView1.DefaultCellStyle.BackColor,
        Location = new Point(cellRect.X, cellRect.Y),
        Size = new Size(cellRect.Width - 2, cellRect.Height - 2)
    };

    // 根据内容高度判断是否显示滚动条
    var textSize = TextRenderer.MeasureText(_scrollTxtBox.Text, _scrollTxtBox.Font, 
        new Size(_scrollTxtBox.Width, int.MaxValue), TextFormatFlags.WordBreak);
    _scrollTxtBox.ScrollBars = textSize.Height > _scrollTxtBox.Height ? ScrollBars.Vertical : ScrollBars.None;

    dataGridView1.Controls.Add(_scrollTxtBox);
    _scrollTxtBox.Focus();
}

private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
    if (_scrollTxtBox == null || e.ColumnIndex != 2) return;

    // 将内容写回单元格
    dataGridView1[e.ColumnIndex, e.RowIndex].Value = _scrollTxtBox.Text;
    dataGridView1.Controls.Remove(_scrollTxtBox);
    _scrollTxtBox.Dispose();
    _scrollTxtBox = null;
}

// 处理列宽/行高变化时的TextBox尺寸调整
private void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
    AdjustScrollTextBoxSize(e.Column.Index);
}

private void dataGridView1_RowHeightChanged(object sender, DataGridViewRowEventArgs e)
{
    AdjustScrollTextBoxSize(dataGridView1.CurrentCell?.ColumnIndex ?? -1);
}

private void AdjustScrollTextBoxSize(int columnIndex)
{
    if (_scrollTxtBox == null || columnIndex != 2 || dataGridView1.CurrentCell == null) return;

    var cellRect = dataGridView1.GetCellDisplayRectangle(columnIndex, dataGridView1.CurrentCell.RowIndex, true);
    _scrollTxtBox.Size = new Size(cellRect.Width - 2, cellRect.Height - 2);

    var textSize = TextRenderer.MeasureText(_scrollTxtBox.Text, _scrollTxtBox.Font, 
        new Size(_scrollTxtBox.Width, int.MaxValue), TextFormatFlags.WordBreak);
    _scrollTxtBox.ScrollBars = textSize.Height > _scrollTxtBox.Height ? ScrollBars.Vertical : ScrollBars.None;
}

注意事项

  1. 若希望固定行高(避免行过高),设置dataGridView1.RowTemplate.Height = 100;(根据需求调整数值),此时内容超过高度会自动显示滚动条。
  2. 必须开启单元格换行:dataGridView1.RowsDefaultCellStyle.WrapMode = DataGridViewTriState.True;,否则文本不会换行,滚动条无法触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 23:27:51