2009-07-28 83 views
6

Khi chạy, tôi đang thêm DataGridView vào biểu mẫu cửa sổ. Cột cuối cùng là một DataGridViewImageColumn:Làm cách nào để hiển thị hình ảnh trong tiêu đề cột datagridview?

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

Thêm đoạn mã sau sẽ nhận được thông tin Biểu tượng của tôi (bitmap) để hiển thị trong mỗi tế bào cột nhưng KHÔNG tiêu đề cột:

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

Ngoài ra, nó là đáng chú ý là hình ảnh hiển thị 'hoàn hảo' trong các tế bào tức là nó có kích thước chính xác để phù hợp với tế bào.

Tuy nhiên, tôi không thể tìm thấy cách thêm cùng một hình ảnh vào ô tiêu đề cột. Sau khi một số googling tôi đã sử dụng đoạn mã sau đã đặt hình ảnh trong ô tiêu đề nhưng để lại cho tôi hai vấn đề:

  1. Hình ảnh không 'tự động định kích thước' vào cột tiêu đề giống như khi nó được thêm vào đến các ô cột. Hình ảnh lớn hơn một chút và bị mờ.
  2. Bằng cách sử dụng sự kiện _CellPainting làm chậm hiệu suất tức là khi di chuột qua DataGridView để đánh dấu hàng đã chọn, làm nổi bật tụt lại phía sau vị trí của con chuột.

Đây là mã:

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 

Có ai biết một cách để giải quyết vấn đề của tôi và có được một hình ảnh sắc nét độc đáo có kích thước vào một headercell DataGridViewImageColumn tại thời gian chạy?

Trả lời

15

Một cách bạn có thể thực hiện việc này là sử dụng sự kiện CellsPainting để vẽ bitmap cho một ô tiêu đề cụ thể. Đây là mã thực hiện điều này giả sử bitmap nằm trong một 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 - Cảm ơn những lời khuyên. Tôi sẽ cung cấp cho thử này và báo cáo lại ... –

+2

Trong trường hợp bạn không lưu trữ hình ảnh trong một ImageList, sửa đổi lần thứ 2 LOC gần nhất; e.Graphics.DrawImage (hình ảnh, pt); cũng hoạt động. –

+0

Nó hoạt động nhưng làm thế nào tôi có thể đặt hình ảnh bên cạnh văn bản với một số đệm? – Jack

0

thử mã này:

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 

nếu bạn đã đọc toàn bộ bài viết để làm điều này kiểm tra liên kết này:

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

2

tôi cần điều phức tạp hơn một chút - hình ảnh thêm ở phía trước văn bản trong một số tiêu đề cột liên quan đến căn chỉnh cột.

Bạn cần phải thực hiện của riêng bạn System.Windows.Forms.DataGridViewColumnHeaderCell và thay thế ColumnHeaderCell:

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

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

Bây giờ là phần hài hước (thực hiện tiêu đề cột của bạn):

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

Bây giờ chúng tôi muốn thêm Paint() phương pháp. Phần khó khăn duy nhất là làm việc với 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); 
    } 

} 

Nếu bạn muốn sử dụng AutoSizeColumnsMode thiết lập để DataGridViewAutoSizeColumnsMode.ColumnHeaders (do đó bạn sẽ AutoFit ảnh văn bản), bạn cần phải ghi đè DataGridViewColumnHeaderCell.GetPreferredSize. Tôi đã làm điều này bằng cách sử dụng triển khai cơ sở và thêm Image.Width + Padding vào đó.

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

LƯU Ý: Tôi đã dành vài giờ đào trong .NET sources cho đến khi tôi figured this out. Hy vọng rằng bạn sẽ không phải làm vậy.

+0

Chúng ta có thể thêm điều khiển bảng điều khiển ngay phía trên 'tiêu đề cột datagridview' không? –

+0

@ KhurramAli Tôi chưa bao giờ thử nghiệm/thử nghiệm ... Tôi nghĩ rằng nó sẽ có thể ... Nếu bạn có thể kiểm tra nó, xin vui lòng cho tôi biết cho dù nó làm việc. – Vyktor

0

Hãy thử này:

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 
Các vấn đề liên quan