This is actually quite easy to do using custom cell painting.
All you need to do is handle the DataGridView
CellPainting
event:
dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);
And in the handler do something like this:
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == -1)
{
e.Paint(e.CellBounds, DataGridViewPaintParts.All &~DataGridViewPaintParts.ContentBackground);
e.Handled = true;
}
}
The code above is very simple - just check if the current cell is in a header row (has a -1 index) then paint everything except the ContentBackground
.
I've only checked this on my Windows 7 machine and it looks fine, it appears that the content background is only used for the sort glyph - you will want to test it on the target environment to make sure you don't need to do any more involved custom painting to keep the ContentBackground without the glyph.
The width of the header cell will still include the space for the glyph. I would generally accept that since changing this becomes a bit messy, but if you must have the width fit the text then something like the following will work.
First set the width in the DataBindingComplete
event of the DataGridView
:
void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
if (dataGridView1.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.AllCells)
{
// Loop over all the columns
foreach (DataGridViewColumn c in dataGridView1.Columns)
{
// Work out the size of the header text
Size s = TextRenderer.MeasureText(c.HeaderText, dataGridView1.Font);
// Change the autosize mode to allow us to see if the header cell has the
// longest text
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
if (s.Width + 10 > c.Width)
{
// If the header cell is longest we set the column width
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
c.Width = s.Width + 10;
}
else
{
// If the header cell is not longest, reset the autosize mode
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
}
}
}
Once you have done that you then need to still allow the column to autosize when the cell text is longer than the header.
For that I used the CellValueChanged
event:
void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
DataGridViewColumn c = dataGridView1.Columns[e.ColumnIndex];
if (c.AutoSizeMode == DataGridViewAutoSizeColumnMode.None)
{
Size s = TextRenderer.MeasureText(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), dataGridView1.Font);
if (s.Width > c.Width)
{
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
}
}
}