2009-07-28 13 views
6

In fase di esecuzione, sto aggiungendo uno DataGridView a un modulo di Windows. La colonna finale è un DataGridViewImageColumn:Come visualizzare un'immagine in un'intestazione di colonna datagridview?

Dim InfoIconColumn As New DataGridViewImageColumn 
MyDataGridView.Columns.Insert(MyDataGridView.Columns.Count, InfoIconColumn) 

aggiungendo il seguente codice otterrà la mia icona delle informazioni (bitmap) per visualizzare in ciascuna delle celle della colonna, ma non l'intestazione di colonna:

Dim InfoIcon As New Bitmap("C:\MyPath\InfoIcon.bmp") 
InfoIconColumn.Image = InfoIcon 

Inoltre, Vale la pena notare che l'immagine viene visualizzata "perfettamente" nelle celle, ovvero è dimensionata correttamente per adattarsi alla cella.

Tuttavia, non riesco a trovare un modo per aggiungere la stessa immagine alla cella di intestazione della colonna. Dopo un po 'googling ho usato il seguente codice che ha messo l'immagine nella cella di intestazione, ma mi ha lasciato con due problemi:

  1. L'immagine non ha 'auto-size' alla headercell colonna nello stesso modo ha fatto quando ha aggiunto alle celle della colonna. L'immagine era leggermente più grande e sfocata.
  2. Utilizzando l'evento _CellPainting ha rallentato le prestazioni, ad esempio quando si passa sopra lo DataGridView per evidenziare la riga selezionata l'evidenziazione è rimasta indietro rispetto al punto in cui è stato posizionato il mouse.

Ecco il codice:

Private Sub MyDataGridView_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles MyDataGridView.CellPainting 
    Dim InfoIcon As Image = Image.FromFile("C:\MyPath\InfoIcon.bmp") 
    If e.RowIndex = -1 AndAlso e.ColumnIndex = MyDataGridView.Columns.Count - 1 Then 
     e.Paint(e.CellBounds, DataGridViewPaintParts.All And Not DataGridViewPaintParts.ContentForeground) 
     e.Graphics.DrawImage(InfoIcon, e.CellBounds) 
     e.Handled = True 
    End If 
End Sub 

Qualcuno sa di un modo per risolvere il mio problema e ottenere un ben dimensioni, immagine nitida in un DataGridViewImageColumn headercell a run-time?

risposta

15

Un modo per eseguire questa operazione è utilizzare l'evento CellsPainting per disegnare la bitmap per una particolare cella di intestazione. Ecco il codice che esegue questo assumendo che la bitmap sia in un 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

@Lucas - Grazie per il consiglio. Darò questo tentativo e riferirò ... –

+2

Nel caso in cui non si memorizzi l'immagine in una lista immagini, modificando la penultima 2 ° LOC; e.Graphics.DrawImage (image, pt); funziona anche –

+0

Funziona ma come posso posizionare l'immagine dal lato del testo con un po 'di padding? – Jack

0

provare questo codice:

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 

se avete letto l'articolo completo per fare questo controllare questo link:

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

2

avevo bisogno cosa più complessa un po '- immagine aggiungendo davanti al testo nello alcune intestazioni di colonna rispetto all'allineamento delle colonne.

è necessario implementare il proprio System.Windows.Forms.DataGridViewColumnHeaderCell e sostituire ColumnHeaderCell:

// Create header and set up image 
YourDataGridViewColumnHeaderCell headerCell = new YourDataGridViewColumnHeaderCell(); 
headerCell.Image = something; 

// Create column 
DataGridViewColumn yourColumn = new DataGridViewTextBoxColumn(); 
// ... 
yourColumn.ColumnHeaderCell = new headerCell; 

Ora la parte divertente (implementazione della vostra intestazione di colonna):

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

Ora vogliamo aggiungere Paint() metodo. L'unica parte difficile sta funzionando con 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); 
    } 

} 

Se si desidera utilizzare AutoSizeColumnsMode set per DataGridViewAutoSizeColumnsMode.ColumnHeaders (così si avrebbe autofit immagine e testo) è necessario sostituire DataGridViewColumnHeaderCell.GetPreferredSize. L'ho fatto utilizzando l'implementazione di base e aggiungendo Image.Width + Padding ad esso.

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); 
} 

NOTA: ho passato diverse ore a scavare in .NET sources fino a quando ho capito questo. Spero che non sia necessario.

+0

Possiamo aggiungere il controllo del pannello appena sopra le intestazioni della colonna 'datagridview'? –

+0

@KhurramAli Non l'ho mai provato/provato ... Penso che dovrebbe essere possibile ... Se riesci a testarlo, per favore fammi sapere se ha funzionato. – Vyktor

0

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 
Problemi correlati