确保dataGridView列中的文本换行
我有一个特定列的dataGridView。 当我在dataGridView中编写长文本时,它会向我显示带有省略号的缩短版本,因为列不够宽,无法显示整个字符串。
| textdsadasda... |
如果我想dataGridView在下一行显示这个文本,或者包装文本,我该怎么办?
| textdsadasda | | dasdasa | (continuation of line above)
如何才能做到这一点?
可以处理细胞画事件可以帮到你
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.Value == null) return; var s = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font); if (s.Width > dataGridView1.Columns[e.ColumnIndex].Width) { using ( Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor)) { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, Brushes.Black, e.CellBounds,StringFormat.GenericDefault); dataGridView1.Rows[e.RowIndex].Height = (int)(s.Height * Math.Ceiling( s.Width / dataGridView1.Columns[e.ColumnIndex].Width)) ; e.Handled = true; } } }
尝试设置
-
.AutoSizeMode
to.DisplayedCells
。 - 将
AutoSizeRowsMode
设置为AllCells
。 -
DataGridView.DefaultCellStyle.WrapMode
到DataGridViewTriState.True
没有必要通过重新粉刷细胞来重新发明轮子。
相反,只需:
- 将
AutoSizeRowsMode
属性设置为AllCells
。 这允许行高与任何包装文本一起增长。 - 将
DataGridView.DefaultCellStyle.WrapMode
设置为DataGridViewTriState.True
以在单元格中包装文本。 - 最重要的是将
DataGridView.AutoSizeColumnsMode
设置为DataGridViewAutoSizeColumnsMode.None
以便列不会自行resize(因此它们保持在用户指定的宽度)。
之后,如果列中没有足够的空间,文本应该换行到下一行。
您可以尝试将DataGridView.DefaultCellStyle.WrapMode
设置为DataGridViewTriState.True
我发现@DeveloperX的答案真的很有用,但有几个小问题:
- 如果有多个单元格需要换行,它会导致某些行闪烁
- 有些单元格的最后一行缺失或被截断(如果有长单词无法包含在文本中,则会发生这种情况)
它还导致缺少单元格边框(但这取决于网格/单元格边框设置)。
我对@DeveloperX代码进行了修改以解决这个问题,并提出了以下代码:
private int _rowMaxHeight = 0; private int _rowDefaultHeight = 0; private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.Value == null || e.RowIndex < 0) { // The WordWrap code is ony executed if requested the cell has a value, // and if this is not the heading row. return; } if (e.ColumnIndex == 0) { // Resetting row max height on each row's first cell _rowMaxHeight = 0; if (_rowDefaultHeight == 0) { /* The default DataGridView row height is saved when the first cell * inside the first row is populated the first time. This is later * used as the minimum row height, to avoid * smaller-than-default rows. */ _rowDefaultHeight = dataGridView1.Rows[e.RowIndex].Height; } } // Word wrap code var sOriginal = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font); var sWrapped = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font, // Is is MeasureString that determines the height given the width, so // that it properly takes the actual wrapping into account dataGridView1.Columns[e.ColumnIndex].Width); if (sOriginal.Width != dataGridView1.Columns[e.ColumnIndex].Width) { using (Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor), fontBrush = new SolidBrush(e.CellStyle.ForeColor)) { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); // The DrawLine calls restore the missing borders: which borders // miss and how to paint them depends on border style settings e.Graphics.DrawLine(new Pen(gridBrush, 1), new Point(e.CellBounds.X - 1, e.CellBounds.Y + e.CellBounds.Height - 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y + e.CellBounds.Height - 1)); e.Graphics.DrawLine(new Pen(gridBrush, 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y - 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y + e.CellBounds.Height - 1)); //Updating the maximum cell height for wrapped text inside the row: // it will later be set to the row height to avoid the flickering // that would occur by setting the height multiple times. _rowMaxHeight = (Math.Ceiling(sWrapped.Height) > _rowMaxHeight) ? (int)Math.Ceiling(sWrapped.Height) : _rowMaxHeight; // The text is generated inside the row. e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, fontBrush, e.CellBounds, StringFormat.GenericDefault); e.Handled = true; } } if (e.ColumnIndex == dataGridView1.ColumnCount -1 && _rowMaxHeight > 0 && _rowMaxHeight != dataGridView1.Rows[e.RowIndex].Height) { // Setting the height only in the last cell, when the full row has been // painted, helps to avoid flickering when more than one row // needs the wrap. dataGridView1.Rows[e.RowIndex].Height = (_rowMaxHeight > _rowDefaultHeight) ? _rowMaxHeight : _rowDefaultHeight; } }
请注意,此代码仍有一个问题尚未解决:文本在单元格内不再垂直居中!
设置此值有助于实现所需的显示
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
除了设置WrapMode = DataGridViewTriState.True;
我同意这个问题的答案只是在单元格上设置了WordWrap
并且会在这个场景中添加它。
我需要根据每个单元格中的数据动态更改颜色和字体样式。 最初我认为由于需要不同的文本颜色,我很难弄清楚如何使DrawString
包含在CellPainting
事件中。
但是,最后我只在CellPainting
事件中设置Cell.Style
属性,然后退出事件而不设置e.Handled = true
。 这样,网格的绘制事件使用了我为每个单元格设置的样式并正确包装了文本。
例如:
datagrid1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Green;