首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 自訂 DataGridView:繼承與覆寫繪製實現列標題、游標變色、三角指示器完整範例

     編輯:關於C語言

繼承 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; }
    // ... 其他屬性
}

初始化外觀設定(OnCreateControl)


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 直接繪製背景,避免樣式物件配置開銷。

列首三角指示器(OnRowPostPaint / OnRowPrePaint)


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);
    // 預繪邏輯(可選)
}

點擊列時標記(OnCellClick)


protected override void OnCellClick(DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0 && CurrentRow?.Index == e.RowIndex)
        _clicked = true;
    base.OnCellClick(e);
}

完整自訂繪製(OnCellPainting)—— 核心亮點

覆寫 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,讓預設內容繪製繼續執行
}

使用方式

  1. 將 CustomDataGridView 加入專案,建置專案。
  2. 工具箱會自動出現 CustomDataGridView 控制項,拖曳至表單。
  3. 屬性視窗設定 CellColorOnChange=True、HoverColor、GridColor 等。
  4. 繫結資料來源:customGrid.DataSource = myDataTable;

擴充方向建議

  • 奇偶列斑馬紋: 在 OnRowPrePaint 依 e.RowIndex % 2 切換背景色。
  • 資料列分組標題: 覆寫 OnRowPostPaint 繪製跨列群組標籤。
  • 儲存格層級條件格式: 在 OnCellPainting 依資料值動態改變前景/背景/字型。
  • 虛擬模式支援: 實作 CellValueNeeded 配合大量資料(>10萬列)顯示。
  • 高 DPI 適配: 使用 e.Graphics.DpiX/Y 縮放繪製尺寸,或改用 DataGridView.AdvancedCellBorderStyle 設定邊框。

掌握 DataGridView 繪製管線(OnCellPainting、OnRowPostPaint、OnRowPrePaint),即可打造出專業級、符合品牌風格的資料表格元件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved