DataGridView二维表头与合并单元格
1、在项目中添加“组件类”。
2、所引用的命名空间如下:
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Collections;
using System.ComponentModel; using System.Windows.Forms; using System.Drawing;
using System.Drawing.Design; using System.Diagnostics;
3、DataGridView二维表头与合并单元格类,继承DataGridView类
public partial class HeaderUnitView : DataGridView {
private TreeView[] _columnTreeView;
private ArrayList _columnList = new ArrayList();
private int _cellHeight = 17; public int CellHeight {
get { return _cellHeight; } set { _cellHeight = value; } }
private int _columnDeep = 1;
private bool HscrollRefresh = false; /// /// 水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误 ///
[Description(\"水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误\")]
public bool RefreshAtHscroll {
get { return HscrollRefresh; } set { HscrollRefresh = value; } }
///
public HeaderUnitView() {
InitializeComponent(); this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; //设置列高度显示模式 }
public HeaderUnitView(IContainer container) {
container.Add(this); InitializeComponent(); }
[Description(\"设置或获得合并表头树的深度\")] public int ColumnDeep { get {
if (this.Columns.Count == 0) _columnDeep = 1;
this.ColumnHeadersHeight = _cellHeight * _columnDeep; return _columnDeep; } set
{
if (value < 1)
_columnDeep = 1; else
_columnDeep = value;
this.ColumnHeadersHeight = _cellHeight * _columnDeep; } }
[Description(\"添加合并式单元格绘制的所需要的节点对象\")] public TreeView[] ColumnTreeView {
get { return _columnTreeView; } set {
if (_columnTreeView != null) {
for (int i = 0; i <= _columnTreeView.Length - 1; i++) _columnTreeView[i].Dispose(); }
_columnTreeView = value; } }
[Description(\"设置添加的字段树的相关属性\")] public TreeView ColumnTreeViewNode {
get { return _columnTreeView[0]; } }
/// /// 设置或获取合并列的集合 ///
[MergableProperty(false)]
[Editor(\"System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\ [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
[Localizable(true)]
[Description(\"设置或获取合并列的集合\"), Browsable(true), Category(\"单元格合并\")] public List return _mergecolumnname; } set { _mergecolumnname = value; } } private List if (_columnTreeView == null) return null; if (_columnTreeView[0] == null) return null; if (_columnTreeView[0].Nodes == null) return null; if (_columnTreeView[0].Nodes.Count == 0) return null; _columnList.Clear(); GetNadirColumnNodes(_columnList, _columnTreeView[0].Nodes[0], false); return _columnList; } } /// ///绘制合并表头 /// ///合并表头节点 ///绘图参数集 ///结点深度 /// System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int level) { //根节点时退出递归调用 if (level == 0) return; RectangleF uhRectangle; int uhWidth; SolidBrush gridBrush = new SolidBrush(this.GridColor); SolidBrush backColorBrush = new SolidBrush(e.CellStyle.BackColor); Pen gridLinePen = new Pen(gridBrush); StringFormat textFormat = new StringFormat(); textFormat.Alignment = StringAlignment.Center; uhWidth = GetUnitHeaderWidth(node); if (node.Nodes.Count == 0) { uhRectangle = new Rectangle(e.CellBounds.Left, e.CellBounds.Top + node.Level * _cellHeight, uhWidth - 1, _cellHeight * (_columnDeep - node.Level) - 1); } else { uhRectangle = new Rectangle( e.CellBounds.Left, e.CellBounds.Top + node.Level * _cellHeight, uhWidth - 1, _cellHeight - 1); } //画矩形 e.Graphics.FillRectangle(backColorBrush, uhRectangle); //划底线 e.Graphics.DrawLine(gridLinePen , uhRectangle.Left , uhRectangle.Bottom , uhRectangle.Right , uhRectangle.Bottom); //划右端线 e.Graphics.DrawLine(gridLinePen , uhRectangle.Right , uhRectangle.Top , uhRectangle.Right , uhRectangle.Bottom); ////写字段文本 e.Graphics.DrawString(node.Text, this.Font , new SolidBrush(e.CellStyle.ForeColor) , uhRectangle.Left + uhRectangle.Width / 2 - e.Graphics.MeasureString(node.Text, this.Font).Width / 2 - 1 , uhRectangle.Top + uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.Font).Height / 2); //递归调用() if (node.PrevNode == null) if (node.Parent != null) PaintUnitHeader(node.Parent, e, level - 1); } /// /// 获得合并标题字段的宽度 /// /// 字段节点 /// private int GetUnitHeaderWidth(TreeNode node) { //获得非最底层字段的宽度 int uhWidth = 0; //获得最底层字段的宽度 if (node.Nodes == null) return this.Columns[GetColumnListNodeIndex(node)].Width; if (node.Nodes.Count == 0) return this.Columns[GetColumnListNodeIndex(node)].Width; for (int i = 0; i <= node.Nodes.Count - 1; i++) { uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes[i]); } return uhWidth; } /// /// 获得底层字段索引 /// ///' 底层字段节点 /// private int GetColumnListNodeIndex(TreeNode node) { for (int i = 0; i <= _columnList.Count - 1; i++) { if (((TreeNode)_columnList[i]).Equals(node)) return i; } return -1; } /// /// 获得底层字段集合 /// /// 底层字段集合 /// 字段节点 /// 向上搜索与否 /// private void GetNadirColumnNodes( ArrayList alList, TreeNode node, Boolean isChecked) { if (isChecked == false) { if (node.FirstNode == null) { alList.Add(node); if (node.NextNode != null) { GetNadirColumnNodes(alList, node.NextNode, false); return; } if (node.Parent != null) { GetNadirColumnNodes(alList, node.Parent, true); return; } } else { if (node.FirstNode != null) { GetNadirColumnNodes(alList, node.FirstNode, false); return; } } } else { if (node.FirstNode == null) { return; } else { if (node.NextNode != null) { GetNadirColumnNodes(alList, node.NextNode, false); return; } if (node.Parent != null) { GetNadirColumnNodes(alList, node.Parent, true); return; } } } } /// /// 滚动 /// /// protected override void OnScroll(ScrollEventArgs e) { bool scrollDirection = (e.ScrollOrientation == ScrollOrientation.HorizontalScroll); base.OnScroll(e); if (RefreshAtHscroll && scrollDirection) this.Refresh(); } /// /// 列宽度改变的重写 /// /// protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e) { Graphics g = Graphics.FromHwnd(this.Handle); float uwh = g.MeasureString(e.Column.HeaderText, this.Font).Width; if (uwh >= e.Column.Width) { e.Column.Width = Convert.ToInt16(uwh); } base.OnColumnWidthChanged(e); } /// /// 单元格绘制(重写) /// /// /// OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e) { try { if (e.RowIndex > -1 && e.ColumnIndex > -1) { DrawCell(e); } void else { //行标题不重写 if (e.ColumnIndex < 0) { base.OnCellPainting(e); return; } if (_columnDeep == 1) { base.OnCellPainting(e); return; } //绘制表头 if (e.RowIndex == -1) { if (e.ColumnIndex >= NadirColumnList.Count) { e.Handled = true; return; } PaintUnitHeader((TreeNode)NadirColumnList[e.ColumnIndex] , e , _columnDeep); e.Handled = true; } } } catch { } } #region 合并单元格 /// /// private void DrawCell(DataGridViewCellPaintingEventArgs e) { if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet) { e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; } Brush gridBrush = new SolidBrush(this.GridColor); SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor); SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor); int cellwidth; //上面相同的行数 int UpRows = 0; //下面相同的行数 int DownRows = 0; //总行数 int count = 0; if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -1) { cellwidth = e.CellBounds.Width; Pen gridLinePen = new Pen(gridBrush); string curValue = e.Value == null ? \"\" : e.Value.ToString().Trim(); string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? \"\" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim(); if (!string.IsNullOrEmpty(curValue)) { #region 获取下面的行数 for (int i = e.RowIndex; i < this.Rows.Count; i++) { if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue)) { //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected; DownRows++; if (e.RowIndex != i) { cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width; } } else { break; } } #endregion #region 获取上面的行数 for (int i = e.RowIndex; i >= 0; i--) { if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue)) { //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected; UpRows++; if (e.RowIndex != i) { cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width; } } else { break; } } #endregion count = DownRows + UpRows - 1; if (count < 2) { return; } } if (this.Rows[e.RowIndex].Selected) { backBrush.Color = e.CellStyle.SelectionBackColor; fontBrush.Color = e.CellStyle.SelectionForeColor; } //以背景色填充 e.Graphics.FillRectangle(backBrush, e.CellBounds); //画字符串 PaintingFont(e, cellwidth, UpRows, DownRows, count); if (DownRows == 1) { e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); count = 0; } // 画右边线 e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom); e.Handled = true; } } /// /// /// /// /// /// private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count) { SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor); int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height; int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width; int cellheight = e.CellBounds.Height; if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y + cellheight * DownRows - fontheight); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1)); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1)); } else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight) { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1)); } else { e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2); } } #endregion } 4、HeaderUnitView控件的具体使用方法 示例界面:重新生成解决方案后,直接在工具栏拖放控件(下面是两种方法) 一、通过属性设置 (1)设置ColumnHeadersHeightSizeMode属性为:DisableResizing (2)编辑列 (3)设置ColumnDeep属性为:2;设置CellHeight和ColumnHeadersHeight属性 (4)设置ColumnTreeView属性,添加TreeView (5)设置ColumnTreeViewNode属性,为TreeView添加节点。(在ColumnTreeView中属性 中的Node里添加节点如下) (6)设置RefreshAtHscroll属性为True。 (7)利用DataGridView方法绑定数据即可。 二、通过代码设置 //添加列 DataGridViewTextBoxColumn tcDM = new DataGridViewTextBoxColumn(); tcDM.HeaderText = \"班级代码\"; tcDM.Name = \"DM\"; //tcDM.DataPropertyName = \"DM\"; tcDM.ReadOnly = true; //tcDM.SortMode = DataGridViewColumnSortMode.NotSortable; //tcDM.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; dgv.Columns.Add(tcDM); DataGridViewTextBoxColumn tcMC = new DataGridViewTextBoxColumn(); tcMC.HeaderText = \"班级名称\"; tcMC.Name = \"MC\"; tcMC.ReadOnly = true; dgv.Columns.Add(tcMC); DataGridViewTextBoxColumn tcNan = new DataGridViewTextBoxColumn(); tcNan.HeaderText = \"男\"; tcNan.Name = \"Nan\"; tcNan.ReadOnly = true; dgv.Columns.Add(tcNan); DataGridViewTextBoxColumn tcNv = new DataGridViewTextBoxColumn(); tcNv.HeaderText = \"女\"; tcNv.Name = \"Nv\"; tcNv.ReadOnly = true; dgv.Columns.Add(tcNv); //增加TreeView TreeView tv = new TreeView(); TreeNode tnDM = new TreeNode(\"班级代码\"); tv.Nodes.Add(tnDM); TreeNode tnMC = new TreeNode(\"班级名称\"); tv.Nodes.Add(tnMC); TreeNode tnSex = new TreeNode(\"性别\"); tv.Nodes.Add(tnSex); TreeNode tnNan = new TreeNode(\"男\"); tnSex.Nodes.Add(tnNan); TreeNode tnNv = new TreeNode(\"女\"); tnSex.Nodes.Add(tnNv); dgv.ColumnTreeView = new TreeView[] { tv }; //设置其他属性 dgv.AutoGenerateColumns = false; //不自动增加列 dgv.RowHeadersVisible = false; //行头不可见 dgv.AllowUserToAddRows = false; dgv.RowTemplate.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; dgv.ColumnDeep = 2; dgv.CellHeight = 25; dgv.ColumnHeadersHeight = 50; dgv.RefreshAtHscroll = true; 三、添加一条数据 dgv.Rows.Add(); //添加行 dgv.Rows[0].Cells[\"DM\"].Value = \"2003001\"; dgv.Rows[0].Cells[\"MC\"].Value = \"网络一班\"; ; dgv.Rows[0].Cells[\"Nan\"].Value = \"26人\"; dgv.Rows[0].Cells[\"Nv\"].Value = \"18人\"; 四、合并单元格 headerUnitView1.MergeColumnNames.Add(\"Column11\");//Column11需要合并单元格的列 -------------------------------------------------------------------------------------------------- 如果有三层表头就把ColumnDeep改成3,,依次... 因篇幅问题不能全部显示,请点此查看更多更全内容