I needed a bit more complicated: adding an image in front of the text to the column headers relative to the alignment of the columns.
You need to implement your own System.Windows.Forms.DataGridViewColumnHeaderCell and replace ColumnHeaderCell :
// Create header and set up image YourDataGridViewColumnHeaderCell headerCell = new YourDataGridViewColumnHeaderCell(); headerCell.Image = something; // Create column DataGridViewColumn yourColumn = new DataGridViewTextBoxColumn(); // ... yourColumn.ColumnHeaderCell = new headerCell;
Now the funny part (implementing your column header):
class YourDataGridViewColumnHeaderCell : System.Windows.Forms.DataGridViewColumnHeaderCell {
Now we want to add the Paint() method. The only tricky part is working with System.Windows.Forms.DataGridViewPaintParts .
protected override void Paint( Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates dataGridViewElementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts ) { // Outside header or without an image, use default painting if ((rowIndex != -1) || (Image == null)) { base.Paint( graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts ); return; } // Borders, background, focus selection can remain the same // But Foreground will have different image base.Paint( graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts & ~DataGridViewPaintParts.ContentForeground ); // Repainting of content background (that where we want to place our image) if ((paintParts & DataGridViewPaintParts.ContentBackground) != DataGridViewPaintParts.None) { // +4 is hardcoded margin Point bounds = new Point( cellBounds.X + 4, cellBounds.Y ); // Handle vertical alignment correctly switch (cellStyle.Alignment) { // Top case DataGridViewContentAlignment.TopLeft: case DataGridViewContentAlignment.TopCenter: case DataGridViewContentAlignment.TopRight: // Already set break; // Middle case DataGridViewContentAlignment.MiddleLeft: case DataGridViewContentAlignment.MiddleCenter: case DataGridViewContentAlignment.MiddleRight: bounds.Y = cellBounds.Y + (cellBounds.Height - Image.Height) / 2; break; // Bottom case DataGridViewContentAlignment.BottomLeft: case DataGridViewContentAlignment.BottomCenter: case DataGridViewContentAlignment.BottomRight: bounds.Y = cellBounds.Y + (cellBounds.Height - Image.Height); break; } graphics.DrawImage( Image, bounds ); } // Foreground should be shifted by left image margin + image.width + right // image margin and of course target spot should be a bit smaller if ((paintParts & DataGridViewPaintParts.ContentForeground) != DataGridViewPaintParts.None) { Rectangle newCellBounds = new Rectangle( cellBounds.X + 4 + Image.Width + 4, cellBounds.Y, cellBounds.Width - Image.Width - 8, cellBounds.Height ); base.Paint( graphics, clipBounds, newCellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, DataGridViewPaintParts.ContentForeground ); } }
If you want to use AutoSizeColumnsMode , set DataGridViewAutoSizeColumnsMode.ColumnHeaders (so you have to auto-image the image and ), you need to override DataGridViewColumnHeaderCell.GetPreferredSize . I did this using the base implementation and adding Image.Width + Padding to it.
protected override Size GetPreferredSize( Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex,Size constraintSize ) { // Load up original image Size original = base.GetPreferredSize( graphics, cellStyle, rowIndex, constraintSize ); // Ensure the image is set and that we are working on header if ((rowIndex != -1) || (Image == null)) { return original; } // -1 is reserved value if (original.Width < 0) { return original; } return new Size( original.Width + Image.Width + 4, original.Height ); }
NOTE I spent several hours searching for .NET sources until I realized this. I hope you donβt have to.