How to display an image in a datagridview column header?

前端 未结 4 533
傲寒
傲寒 2020-12-03 15:40

At run-time, I am adding a DataGridView to a windows form. The final column is a DataGridViewImageColumn:

Dim InfoIconColumn As New         


        
相关标签:
4条回答
  • 2020-12-03 16:06

    try this code:

        Private Sub DataGridView1_CellPainting(ByVal sender As System.Object, _
                ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) _
                Handles DataGridView1.CellPainting
            If e.RowIndex = -1 AndAlso e.ColumnIndex = DataGridView1.Columns.Count - 1 Then
                e.Paint(e.CellBounds, DataGridViewPaintParts.All And Not DataGridViewPaintParts.ContentForeground)
                e.Graphics.DrawImage(IconImg, e.CellBounds)
                e.Handled = True
            End If
        End Sub
    

    if you have read full article for doing this check This link:

    http://www.authorcode.com/add-image-on-datagridview-column-header-in-vb-net/

    0 讨论(0)
  • 2020-12-03 16:18

    I needed a bit more complex thing - adding image in front of text in some column headers with respect to column alignment.

    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 (implementation of your column header):

    class YourDataGridViewColumnHeaderCell : System.Windows.Forms.DataGridViewColumnHeaderCell
    {
        // Set up image as you want
        System.Drawing.Image Image { get; set; }
    }
    

    Now we want to add 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's 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 to DataGridViewAutoSizeColumnsMode.ColumnHeaders (so you would autofit image and text) you need to override DataGridViewColumnHeaderCell.GetPreferredSize. I did this by using 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've spent several hours digging in .NET sources until I figured this out. Hopefully you won't have to.

    0 讨论(0)
  • 2020-12-03 16:21

    One way you can do this is to use the CellsPainting event to draw the bitmap for a particular header cell. Here is code that does this assuming the bitmap is in an imagelist.

    //this.images is an ImageList with your bitmaps
    void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.ColumnIndex == 1 && e.RowIndex == -1)
        {
            e.PaintBackground(e.ClipBounds, false);
    
            Point pt = e.CellBounds.Location;  // where you want the bitmap in the cell
    
            int offset = (e.CellBounds.Width - this.images.ImageSize.Width) / 2;
            pt.X += offset;
            pt.Y += 1;
            this.images.Draw(e.Graphics, pt, 0);
            e.Handled = true;
        }
    }
    
    0 讨论(0)
  • 2020-12-03 16:25

    Try This:

    Private Sub DataGridView1_CellPainting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
            If e.RowIndex > -1 Then
    
                If e.ColumnIndex = -1 Then
                    e.Paint(e.CellBounds, DataGridViewPaintParts.Focus And Not DataGridViewPaintParts.ContentForeground)
                    DataGridView1.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single
                    e.Graphics.DrawImage(IconImg, e.CellBounds)
                    e.Handled = True
                    'DataGridView1.RowHeadersWidth = 100
                    'DataGridView1.ColumnHeadersHeight = 25
                End If
    
            End If
    
    0 讨论(0)
提交回复
热议问题