Benutzerdefinierter DataGridView ColumnHeader
Frank Dzaebel, erstellt am: 10.11.2007, zuletzt geändert: 10.11.2007
Kategorie:DataGridView, .NET-Version:2.0 

In diesem Artikel wird eine Technik vorgestellt, wie man benutzerdefinierte Spaltenüberschriften beim DataGridView erreicht. Hier sind es Gruppierungs-Label, wie im Bild zu sehen. Die Gruppierungs-Label bewegen sich bei Scroll-Aktionen mit:

Anwendung mit Gruppen-Labels
Weiterführende Literatur:
- Building a Drop-Down Filter List for a DataGridView Column Header Cell

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;

namespace UserConfigDelete
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    Properties.Settings Props = Properties.Settings.Default;
    static public MyDgv dgv = new MyDgv();
    const int anzSpalten = 6;
    const int anzZeilen = 4;
    const int yHeaderPadding = 10;
    const int columnHeadersHeight = 40;

    private void Form1_Load(object sender, EventArgs e)
    {
      DgvAddColumns(anzSpalten); DgvAddRows(anzZeilen);
      dgv.ColumnHeadersDefaultCellStyle.Padding =
        new Padding(0, yHeaderPadding, 0, 0);
      dgv.ColumnHeadersHeight = columnHeadersHeight;
      dgv.Dock = DockStyle.Fill; Controls.Add(dgv);
      dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    }

    private void DgvAddRows(int anzZeilen)
    {
      for (int i = 0; i < anzZeilen; i++)
      {
        int index = dgv.Rows.Add();
        foreach (DataGridViewCell cell in dgv.Rows[index].Cells)
          cell.Value = "Wert" + i + cell.ColumnIndex;
      }
    }

    private void DgvAddColumns(int anzSpalten)
    {
      for (int i = 0; i < anzSpalten; i++)
        dgv.Columns.Add("Spalte" + i, "Spalte" + i);
    }

    #region MyDgv
    public class MyDgv : DataGridView
    {
      List<TransparentLabel> grpLabels = new List<TransparentLabel>();

      protected override void OnColumnAdded(DataGridViewColumnEventArgs e)
      {
        base.OnColumnAdded(e);
        GruppenLabelAktualisieren(ref grpLabels);
      }

      protected override void OnColumnRemoved(DataGridViewColumnEventArgs e)
      {
        base.OnColumnRemoved(e);
        GruppenLabelAktualisieren(ref grpLabels);
      }
      Font lblFont = new Font("Arial", 12, FontStyle.Bold | FontStyle.Underline, GraphicsUnit.Pixel);

      private void GruppenLabelAktualisieren(ref List<TransparentLabel> grpLabels)
      {
        grpLabels.Clear();
        for (int i = 0; i < Columns.Count / 2; i++)
        {
          TransparentLabel lbl = new TransparentLabel();
          lbl.Text = "Gruppe" + i; lbl.AutoSize = true;
          lbl.Font = lblFont; lbl.Visible = false;
          Controls.Add(lbl);
          lbl.BringToFront(); grpLabels.Add(lbl);
        }
      }

      const int topAbstand = 3;
      protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
      {
        base.OnCellPainting(e);
        if (e.RowIndex != -1) { return; }
        Point loc; if (e.ColumnIndex < 0) return;
        TransparentLabel lbl = grpLabels[e.ColumnIndex / 2];
        if (e.ColumnIndex % 2 == 0)
        {
          loc = e.CellBounds.Location;
          loc.Offset(e.CellBounds.Width - lbl.Width / 2, Top + topAbstand);
          lbl.Location = loc; lbl.Visible = true; lbl.Invalidate();
          return;
        }
        if (e.ColumnIndex % 2 == 1)
        {
          loc = e.CellBounds.Location;
          loc.Offset(-lbl.Width / 2, Top + topAbstand);
          lbl.Location = loc; lbl.Visible = true;  
        }
      }

      protected override void OnScroll(ScrollEventArgs e)
      {
        base.OnScroll(e);
        foreach (TransparentLabel lbl in grpLabels)
          lbl.Invalidate();
        for (int col=0; col<dgv.Columns.Count; col++)
          InvalidateCell(col,-1);
      }
    }
    #endregion

    #region TransparentLabel

    /// <summary>Transparenter Label</summary>
    public class TransparentLabel : System.Windows.Forms.Label
    {
      public TransparentLabel()
      {
        this.BackColor = Color.Transparent;
        this.DoubleBuffered = false;
      }

      int WS_EX_TRANSPARENT = 0x20;
      protected override CreateParams CreateParams
      {
        get
        {
          CreateParams cp = base.CreateParams;
          cp.ExStyle |= WS_EX_TRANSPARENT;
          return cp;
        }
      }

      protected override void OnPaintBackground(PaintEventArgs pevent)
      {
      }
    }
    #endregion
  }
}