繼承 DataGridView 並覆寫繪製相關方法,可實現高度客製化的表格外觀:漸層標題列、資料列游標變色、列首三角指示器、自訂格線顏色等。本文提供完整可編譯的程式碼結構,說明關鍵覆寫點與實作細節。
public class CustomDataGridView : DataGridView
{
// 外觀設定屬性
private bool _cellColorOnChange = false;
private Color _hoverColor = Color.Yellow;
private bool _showTriangle = true;
private Color _gridColor = Color.FromArgb(236, 233, 216);
private bool _clicked = false;
private Color _defaultRowColor;
public CustomDataGridView()
{
// 雙重緩衝減少閃爍
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
// 屬性暴露給設計器/程式碼設定
public bool CellColorOnChange { get => _cellColorOnChange; set => _cellColorOnChange = value; }
public Color HoverColor { get => _hoverColor; set => _hoverColor = value; }
public bool ShowTriangle { get => _showTriangle; set => _showTriangle = value; }
public Color GridColor { get => _gridColor; set => _gridColor = value; }
// ... 其他屬性
}
protected override void OnCreateControl()
{
base.OnCreateControl();
EnableHeadersVisualStyles = false; // 關閉視覺樣式,自行繪製
// 標題列樣式
ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(236, 233, 216);
ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Raised;
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
ColumnHeadersDefaultCellStyle.ForeColor = SystemColors.WindowText;
ColumnHeadersDefaultCellStyle.SelectionBackColor = SystemColors.Highlight;
ColumnHeadersDefaultCellStyle.SelectionForeColor = SystemColors.HighlightText;
// 列標題樣式
RowHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
RowHeadersDefaultCellStyle.BackColor = Color.FromArgb(236, 233, 216);
RowHeadersDefaultCellStyle.ForeColor = SystemColors.WindowText;
RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Raised;
// 資料列預設選取色
DefaultCellStyle.SelectionBackColor = Color.DarkBlue;
DefaultCellStyle.SelectionForeColor = Color.DarkSlateBlue;
RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
BackgroundColor = SystemColors.Window;
BorderStyle = BorderStyle.Fixed3D;
AllowUserToOrderColumns = true;
AutoGenerateColumns = true;
}
// 滑鼠進入儲存格:記錄原底色
protected override void OnCellMouseEnter(DataGridViewCellEventArgs e)
{
base.OnCellMouseEnter(e);
if (_cellColorOnChange && e.RowIndex >= 0)
_defaultRowColor = Rows[e.RowIndex].DefaultCellStyle.BackColor;
}
// 滑鼠移動:套用游標色
protected override void OnCellMouseMove(DataGridViewCellMouseEventArgs e)
{
base.OnCellMouseMove(e);
if (_cellColorOnChange && e.RowIndex >= 0)
Rows[e.RowIndex].DefaultCellStyle.BackColor = _hoverColor;
}
// 滑鼠離開:還原底色
protected override void OnCellMouseLeave(DataGridViewCellEventArgs e)
{
base.OnCellMouseLeave(e);
if (_cellColorOnChange && e.RowIndex >= 0)
Rows[e.RowIndex].DefaultCellStyle.BackColor = _defaultRowColor;
}
效能提示: 頻繁修改 DefaultCellStyle 會觸發重繪,大量資料時建議改用 OnCellPainting 直接繪製背景,避免樣式物件配置開銷。
protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
{
base.OnRowPostPaint(e);
if (!_showTriangle) return;
using (var brush = new SolidBrush(Color.Black))
{
// 假設專案資源有名為 "Triangle" 的 8x13 圖片
// var img = Properties.Resources.Triangle;
// 若無資源,可改用文字 "▶" 或自行繪製三角形
if (_clicked && e.RowIndex == CurrentRow?.Index)
{
// e.Graphics.DrawImageUnscaled(img, e.RowBounds.X + 1, e.RowBounds.Y + 2, 8, 13);
e.Graphics.DrawString("▶", e.InheritedRowStyle.Font, brush, e.RowBounds.X + 5, e.RowBounds.Y + 4);
}
}
}
protected override void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e)
{
base.OnRowPrePaint(e);
// 預繪邏輯(可選)
}
protected override void OnCellClick(DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && CurrentRow?.Index == e.RowIndex)
_clicked = true;
base.OnCellClick(e);
}
覆寫 OnCellPainting 可完全掌控每個儲存格的外觀:左上角、標題列、列標題、資料儲存格。
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
base.OnCellPainting(e);
var headerBrush = new SolidBrush(Color.FromArgb(236, 233, 216));
var gridPen = new Pen(_gridColor, 1);
// 1. 左上角角落儲存格 (ColumnIndex=-1, RowIndex=-1)
if (e.ColumnIndex == -1 && e.RowIndex == -1)
{
using (var lgb = new LinearGradientBrush(e.CellBounds, Color.Gray, Color.Gray, LinearGradientMode.ForwardDiagonal))
{
e.Graphics.FillRectangle(headerBrush, e.CellBounds);
var border = e.CellBounds; border.Offset(-1, -1);
e.Graphics.DrawRectangle(Pens.Gray, border);
}
e.PaintContent(e.CellBounds);
e.Handled = true;
return;
}
// 2. 標題列 (RowIndex=-1)
if (e.RowIndex == -1)
{
using (var lgb = new LinearGradientBrush(e.CellBounds, Color.Silver, Color.Silver, LinearGradientMode.Vertical))
{
e.Graphics.FillRectangle(headerBrush, e.CellBounds);
var border = e.CellBounds; border.Offset(-1, -1);
e.Graphics.DrawRectangle(Pens.Silver, border);
}
e.PaintContent(e.CellBounds);
e.Handled = true;
return;
}
// 3. 列標題 (ColumnIndex=-1)
if (e.ColumnIndex == -1)
{
using (var lgb = new LinearGradientBrush(e.CellBounds, Color.Silver, Color.Silver, LinearGradientMode.Horizontal))
{
e.Graphics.FillRectangle(headerBrush, e.CellBounds);
var border = e.CellBounds; border.Offset(-1, -1);
e.Graphics.DrawRectangle(Pens.Silver, border);
// 可在此繪製排序箭頭等
}
e.PaintContent(e.CellBounds);
e.Handled = true;
return;
}
// 4. 一般資料儲存格:僅畫格線
var borderRect = e.CellBounds; borderRect.Offset(-1, -1);
e.Graphics.DrawRectangle(gridPen, borderRect);
// 不設 e.Handled = true,讓預設內容繪製繼續執行
}
CustomDataGridView 加入專案,建置專案。CustomDataGridView 控制項,拖曳至表單。CellColorOnChange=True、HoverColor、GridColor 等。customGrid.DataSource = myDataTable;OnRowPrePaint 依 e.RowIndex % 2 切換背景色。OnRowPostPaint 繪製跨列群組標籤。OnCellPainting 依資料值動態改變前景/背景/字型。CellValueNeeded 配合大量資料(>10萬列)顯示。e.Graphics.DpiX/Y 縮放繪製尺寸,或改用 DataGridView.AdvancedCellBorderStyle 設定邊框。掌握 DataGridView 繪製管線(OnCellPainting、OnRowPostPaint、OnRowPrePaint),即可打造出專業級、符合品牌風格的資料表格元件。