昨天一個朋友突然問我如何在C#下給DataGridView繪製背景圖,以前使用一些第三方控制項時,看見它們有這個功能,只是我還沒有過這種需求,於是便動手試了下。
最先想到的是BackgroundImage,這兩天正在做B/S的介面,還覺得要說做介面方便,還得說CSS,從這點上來說,WPF或者Silverlight還真不賴,只可惜的是現在C/S的用武之地越來越小,除了遊戲必須(當然,是大型的遊戲)為傳統型應用程式外,貌似使用C/S做個管理系統實無必要;在企業管理系統中,WPF和Silverlight莫非就是傳中的屠龍技?
又說遠了去了,但是很快發現BackgroundImage不行,且看其定義:
[Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override Image BackgroundImage { get; set; }
不可見的,一個刻意對開發工具隱藏了的屬性,你能指望它會有功能?不死心,代碼中一試,如果沒有任何效果。
於是想起來終極大法:OnPaint方法,一般情況下在控制項中,重寫這個方法,肯定能繪製出來你想要的任何形狀,但是在DataGridVeiw控制項中,居然出現了意想不到的問題:
1.當在base.OnPaint(e)之前調用e.Graphics.DrawImage()方法時,資料行的部分是透明的,但是背景部分仍是原來的顏色;
2.當在base.OnPaint(e)之後調用e.Graphics.DrawImage()方法時,DataGridView全部被圖片遮蓋,想想這種情況也是必須的。
難道GridView真沒有辦法繪製背景嗎?我不太相信,於是再探MSDN(很多人平時根本不看MSDN,遇到問題就求救,這樣相當不好),果然發現一個方法:
protected virtual void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds);
看名字就很給力啊,趕緊重寫:
protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds) { graphics.DrawImageUnscaledAndClipped(this.BackgroundImage, gridBounds); }
呵呵,你不讓我使用BackgroundImage,我還非得使用了,BackgroundImage只是被“隱藏”,但是使用還是沒有問題的,正好拿來儲存背景圖片。
果然,運行程式後出結果了,但是又有另一個問題了,資料行的背景是透明的,這樣的話資料就可能被背景影響,導致看不清楚,最好是能給資料行加一個半透明的背景,(此處略過一小時的研究過程...)最終發現有一個方法可以繪製儲存格的背景,儲存格繪製了,資料行不就自然O了嗎?
protected internal virtual void OnCellPainting(DataGridViewCellPaintingEventArgs e);
最終代碼確定了:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Drawing.Drawing2D;namespace WindowsFormsApplication3{ public partial class Form1 : Form { public Form1() { InitializeComponent(); this.dataGridView1.BackgroundImage = Image.FromFile("c:\\2216400.jpg"); this.dataGridView1.DefaultCellStyle.BackColor = Color.FromArgb(128, Color.White); this.dataGridView1.DefaultCellStyle.SelectionBackColor = Color.FromArgb(128, Color.Blue); } } public class MyDataGrid : DataGridView { protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds) { graphics.DrawImageUnscaledAndClipped(this.BackgroundImage, gridBounds); } protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e) { if (e.RowIndex == -1 || e.ColumnIndex == -1) { return; } Rectangle newRect = new Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 4, e.CellBounds.Height - 4); using ( Brush gridBrush = new SolidBrush(this.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor), selectedColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor)) { using (Pen gridLinePen = new Pen(gridBrush)) { if (this.Rows[e.RowIndex].Selected) { e.Graphics.FillRectangle(selectedColorBrush, e.CellBounds); } else { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); } if (e.Value != null) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + 2, StringFormat.GenericDefault); } } e.Handled = true; } } }}
:
這段代碼只能說明一個思路,如果要實用的話肯定得花些力氣,比如說縮放時防止抖動,儲存格的邊框等等,我只是做一個原型,就不繼續深入了。