如何让DataGridView文本单元格的编辑TextBox垂直扩展超出单元格
实现DataGridView编辑TextBox垂直扩展至单元格外
这个需求我之前做WinForms项目时刚好碰到过,其实通过几个事件的配合就能实现,让编辑用的TextBox突破单元格高度限制,方便编辑多行内容。具体实现步骤和代码如下:
1. 确认基础设置(确保单元格单行截断)
首先确保你的DataGridView列已经设置了单行不换行、截断显示的样式,这部分你应该已经完成了,这里再确认下:
// 假设你的目标列是textColumn1 dataGridView1.Columns["textColumn1"].DefaultCellStyle.WrapMode = DataGridViewTriState.False; dataGridView1.Columns["textColumn1"].DefaultCellStyle.Format = ""; // 避免默认格式影响
2. 处理EditingControlShowing事件,初始化编辑TextBox
在这个事件里,我们要把编辑用的TextBox设置为多行模式,同时绑定后续需要的事件:
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { if (e.Control is TextBox editTextBox) { // 加载单元格的完整内容(你已经实现的部分) editTextBox.Text = dataGridView1.CurrentCell.Value?.ToString() ?? string.Empty; // 开启多行模式,允许自动换行 editTextBox.Multiline = true; editTextBox.WordWrap = true; // 添加垂直滚动条,内容过多时方便查看 editTextBox.ScrollBars = ScrollBars.Vertical; // 调整边框样式,和单元格风格匹配 editTextBox.BorderStyle = BorderStyle.FixedSingle; // 先移除旧的事件绑定,避免重复触发 editTextBox.Enter -= EditTextBox_Enter; editTextBox.TextChanged -= EditTextBox_TextChanged; // 绑定事件 editTextBox.Enter += EditTextBox_Enter; editTextBox.TextChanged += EditTextBox_TextChanged; } }
3. 处理TextBox的Enter事件,调整控件位置和大小
当用户开始编辑时,我们要把TextBox的位置对齐单元格,高度扩展到单元格之外:
private void EditTextBox_Enter(object sender, EventArgs e) { if (sender is TextBox editTextBox && dataGridView1.CurrentCell != null) { // 获取当前单元格在DataGridView内的显示区域 Rectangle cellRect = dataGridView1.GetCellDisplayRectangle( dataGridView1.CurrentCell.ColumnIndex, dataGridView1.CurrentCell.RowIndex, false ); // 把单元格的屏幕坐标转换为DataGridView的控件坐标 Point textBoxLocation = dataGridView1.PointToClient( dataGridView1.PointToScreen(cellRect.Location) ); // 设置TextBox的位置和宽度和单元格一致,高度设为一个合适的初始值(比如200) editTextBox.Location = textBoxLocation; editTextBox.Width = cellRect.Width; editTextBox.Height = 200; // 把TextBox放到最顶层,确保不会被其他单元格遮挡 editTextBox.BringToFront(); } }
4. 处理TextBox的TextChanged事件,自动调整高度适配内容
为了让TextBox高度能根据输入的内容自动变化,我们可以在文本改变时计算所需高度:
private void EditTextBox_TextChanged(object sender, EventArgs e) { if (sender is TextBox editTextBox) { // 计算当前文本在指定宽度下需要的高度 Size requiredSize = TextRenderer.MeasureText( editTextBox.Text, editTextBox.Font, new Size(editTextBox.Width, int.MaxValue), TextFormatFlags.WordBreak ); // 设置TextBox高度,加上一点边距避免内容贴边 int newHeight = Math.Max(requiredSize.Height + 10, 100); // 最小高度设为100,避免太矮 // 可选:限制TextBox高度不超出窗体范围 Form parentForm = dataGridView1.FindForm(); if (parentForm != null && editTextBox.Top + newHeight > parentForm.ClientSize.Height) { newHeight = parentForm.ClientSize.Height - editTextBox.Top - 10; } editTextBox.Height = newHeight; } }
5. 处理CellEndEdit事件,完成编辑后清理状态
当用户结束编辑时,我们要把编辑后的内容赋值给单元格,并恢复TextBox的默认状态,避免影响其他单元格的编辑:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { if (dataGridView1.EditingControl is TextBox editTextBox) { // 把编辑后的内容保存到单元格 dataGridView1.CurrentCell.Value = editTextBox.Text; // 恢复TextBox的单行模式和默认高度 editTextBox.Multiline = false; editTextBox.Height = dataGridView1.RowTemplate.Height; editTextBox.ScrollBars = ScrollBars.None; } }
额外注意事项
- 如果你的DataGridView有滚动条,用户在编辑时滚动可能会导致TextBox位置偏移,你可以在
Scroll事件里触发CellEndEdit,强制结束编辑:private void dataGridView1_Scroll(object sender, ScrollEventArgs e) { if (dataGridView1.IsCurrentCellInEditMode) { dataGridView1.EndEdit(); } } - 可以根据自己的需求调整TextBox的初始高度、最小高度等参数,让它更贴合你的界面风格。
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

