我发现 DeveloperX 的回答非常好。但我发现我需要稍微调整一下。首先,我需要确保有问题的列不在 AutoSizeMode 中:
if (dgv.Columns[e.ColumnIndex].AutoSizeMode != DataGridViewAutoSizeColumnMode.None)
throw new InvalidOperationException(String.Format("dgv {0} AutoSizeMode <> 'None'", dgv.Columns[e.ColumnIndex].Name));
我还发现使用
var s = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font);
返回一个字符串长度,不能用于与以像素为单位的 ColumnWidth 进行比较。所以,使用How can I convert a string length to a pixel unit?,我将上面的代码行修改为
var s = e.Graphics.MeasureString(e.Value.ToString(), new Font("Segoe UI", 11, FontStyle.Regular, GraphicsUnit.Pixel));
我还发现直接比较宽度不足以确定何时防止剪裁 - 有一些边缘情况没有被捕获。所以,我换了
if (s.Width > dataGridView1.Columns[e.ColumnIndex].Width)
有一个比率比较(通过实验确定的截止值):
if (e.Value.ToString().Length / (double)dataGridView1.Columns[e.ColumnIndex].Width >= .189)
最后,选中行中的单元格没有高亮显示,所以我添加了以下内容:
SolidBrush backColorBrush;
if (dataGridView1.SelectedRows[0].Index == e.RowIndex)
backColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor);
else
backColorBrush = new SolidBrush(e.CellStyle.BackColor);
最终代码:
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.Value == null || e.RowIndex == -1)
return;
if (dataGridView1.Columns[e.ColumnIndex].AutoSizeMode != DataGridViewAutoSizeColumnMode.None)
throw new InvalidOperationException(Format("dataGridView1 {0} AutoSizeMode <> 'None'", dataGridView1.Columns[e.ColumnIndex].Name));
var s = e.Graphics.MeasureString(e.Value.ToString(), new Font("Segoe UI", 11, FontStyle.Regular, GraphicsUnit.Pixel));
if (e.Value.ToString().Length / (double)dataGridView1.Columns[e.ColumnIndex].Width >= .189)
{
SolidBrush backColorBrush;
if (dataGridView1.SelectedRows[0].Index == e.RowIndex)
backColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor);
else
backColorBrush = new SolidBrush(e.CellStyle.BackColor);
using (backColorBrush)
{
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 = System.Convert.ToInt32((s.Height * Math.Ceiling(s.Width / (double)dataGridView1.Columns[e.ColumnIndex].Width)));
e.Handled = true;
}
}
}