I had a similar difficulty, in that I wanted to use wrapping, but only where I specified it to be wrapped with a newline character.
My solution was to resize the column width based upon the longest string I didn't want wrapped, and then let the wrapping do the rest.
Feel free to try the following, or modify it to suit your purposes.
private void dataGridView_TextItems_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (sender is DataGridView dgv && dgv.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewTextBoxCell cell)
{
SetDGVTextBoxColumnWidth(dgv.Columns[e.ColumnIndex] as DataGridViewTextBoxColumn);
}
}
private void SetDGVTextBoxColumnWidth(DataGridViewTextBoxColumn column)
{
if (column != null)
{
DataGridView dgv = column.DataGridView;
Graphics g = dgv.CreateGraphics();
Font font = dgv.Font;
// Acquire all the relevant cells - the whole column's collection of cells:
List<DataGridViewTextBoxCell> cells = new List<DataGridViewTextBoxCell>();
foreach (DataGridViewRow row in column.DataGridView.Rows)
{
cells.Add(row.Cells[column.Index] as DataGridViewTextBoxCell);
}
// Now find the widest cell:
int widestCellWidth = g.MeasureString(column.HeaderText, font).ToSize().Width; // Start with the header text, but for some reason this seems a bit short.
bool foundNewline = false;
foreach (DataGridViewTextBoxCell cell in cells)
{
font = ((cell.Style.Font != null) ? cell.Style.Font : dgv.Font); // The font may change between cells.
string cellText = cell.Value.ToString().Replace("\r",""); // Ignore any carriage return characters.
if (cellText.Contains('\n'))
{
foundNewline = true;
cell.Style.WrapMode = DataGridViewTriState.True; // This allows newlines in the cell's text to be recognised.
string[] lines = cellText.Split('\n');
foreach (string line in lines)
{
int textWidth = g.MeasureString(line + "_", font).ToSize().Width; // A simple way to ensure that there is room for this text.
widestCellWidth = Math.Max(widestCellWidth, textWidth);
}
}
else
{
int textWidth = g.MeasureString(cellText + "_", font).ToSize().Width;
widestCellWidth = Math.Max(widestCellWidth, textWidth);
}
}
if (foundNewline)
{
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; // Allows us to programatically modify the column width.
column.Width = widestCellWidth; // Simply set the desired width.
}
else
{
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // Allow the system to do the work for us. This does a better job with cell headers.
}
column.Resizable = DataGridViewTriState.False; // We don't wish the User to modify the width of this column manually.
}
}