自定义控件系列<第一篇>--多维表头
来源:互联网 发布:网络授权书制作免费 编辑:程序博客网 时间:2024/06/05 20:10
在NET中,自带的控件很多很强大,一般情况下是足够使用了。但是要满足客户需求和设计需求还是有些远远不够。
在显示数据表格或者操作数据表格的时候,我们往往会采用DataGridView控件去显示数据和操作数据。毕竟一般我们表格的基础功能,在这个控件中已经可以完美实现。
但是在外观方面,比如列标题只是显示一行。有时候我们设计时因为大量的不同数据内容显示在同一张表格中是比较凌乱的,此时需要有大标题和小标题让用户更直观的看清数据本身的归类。而自带的DataGridView控件中没办法这样实现,只能对控件外观进行重绘。
下面分段分析代码的步骤:
本代码主要运用函数:
Dictionary泛型(字典)
Draphics类(绘制)
自定义控件主要重写的三种方法
protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);//绘制界面}protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e){base.OnCellPainting(e);}//绘制表格属性protected override void OnCellClick(DataGridViewCellEventArgs e){base.OnCellClick(e);}//在单元格中单击
执行过程
输入第一个列索引,合并列数,大标题文本
#region 二维表头之合并列 /// <param name="ColIndex">列的索引</param> /// <param name="ColCount">需要合并的列数</param> /// <param name="Text">合并列后的文本</param> public void AddSpanHeader(int CoIindex, int CoICount, string Text)//合并列 { if (CoIindex < 2) { throw new Exception("行宽应大于等于2,合并1列无意义"); } else { //将小标题列加入大标题列中 int Right = CoIindex + CoICount - 1;//同一大标题下的最后一列的索引 TableRows[CoIindex] = new TableTou(Text, 1, CoIindex, Right);//添加标题下的最左列 TableRows[Right] = new TableTou(Text, 3, CoIindex, Right);//添加标题下的最右列 for (int i = CoIindex + 1; i < Right; i++) { TableRows[i] = new TableTou(Text, 2, CoIindex, Right);//添加标题下的中间列 } } }#endregion
选出需要合并的列,存入一个集合中Dictionary。
#region 二维表头之需要合并的列存入Dictionary private Dictionary<int, TableTou> TableRows = new Dictionary<int, TableTou>(); //二维键值数据 private struct TableTou { public TableTou(string Text, int Position, int Left, int Right) { this.Text = Text;//标题文本 this.Position = Position;//位置1左 2中 3右 this.Left = Left;//对应左边 this.Right = Right;//对应右边 } public string Text; public int Position; public int Left; public int Right; } #endregion
重写绘制方法
以上程序把所有需要合并的列都存入Dictionary中,接下来绘制表格的列。
在OnCellPainting方法中发生
判断是否存在在Dictionary集合中
if (TableRows.ContainsKey(e.ColumnIndex))
代码如下:
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)//绘制表格属性 { //e表示父类的表格 if (e.RowIndex == -1) { if (TableRows.ContainsKey(e.ColumnIndex))//判断如果键值中有此索引,则继续运行 { //画边框 Graphics gp = e.Graphics; //单元格背景与边框 e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); //表格标题单元格的X,Y坐标的宽度和高度 int left = e.CellBounds.Left;//X轴 int top = e.CellBounds.Top;//Y轴 int right = e.CellBounds.Right; //y+宽度 int bottom = e.CellBounds.Bottom; //x+高度 //判断键值中的数据 switch (TableRows[e.ColumnIndex].Position) { case 1: left += 2;//最左边 break; case 2: break; case 3: right -= 2;//最右边 break; } //画上半部分的底色 gp.FillRectangle(new SolidBrush(e.CellStyle.BackColor),left,top,right-left,(bottom-top)/2); //画中线 gp.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2, right, (top + bottom) / 2); //小标题 StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center;//垂直对齐 sf.Alignment = StringAlignment.Center;//水平对齐 gp.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black, new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);//小标题信息 left = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Left, true).Left - 2;//获取当前列的X坐标 if (left < 0) { left = this.GetCellDisplayRectangle(-1, -1, true).Width; } right = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Right, true).Right - 2;//获取当前列的Right if (right < 0) { right = this.Width; } //大标题 gp.DrawString(TableRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black, new Rectangle(left, top, right - left, (bottom - top) / 2), sf); e.Handled = true; } } base.OnCellPainting(e); }
全部代码如下:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.Linq;using System.Text;using System.Windows.Forms;using System.Drawing;namespace DataGridView隔行显示不同颜色之两种实现方法.YuanGon_GonNen{ public partial class YuanGo : DataGridView { public YuanGo() { InitializeComponent(); } public YuanGo(IContainer container) { container.Add(this); InitializeComponent(); } //重写方法 protected override void OnPaint(PaintEventArgs e)//绘制界面 { //在执行此方法的过程中发生的任何异常将被忽略 base.OnPaint(e); } protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)//绘制表格属性 { //e表示父类的表格 if (e.RowIndex == -1) { if (TableRows.ContainsKey(e.ColumnIndex))//判断如果键值中有此索引,则继续运行 { //画边框 Graphics gp = e.Graphics; //单元格背景与边框 e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); //表格标题单元格的X,Y坐标的宽度和高度 int left = e.CellBounds.Left;//X轴 int top = e.CellBounds.Top;//Y轴 int right = e.CellBounds.Right; //y+宽度 int bottom = e.CellBounds.Bottom; //x+高度 switch (TableRows[e.ColumnIndex].Position) { case 1: left += 2; break; case 2: break; case 3: right -= 2; break; } //画上半部分的底色 gp.FillRectangle(new SolidBrush(e.CellStyle.BackColor),left,top,right-left,(bottom-top)/2); //画中线 gp.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2, right, (top + bottom) / 2); //小标题 StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center;//垂直对齐 sf.Alignment = StringAlignment.Center;//水平对齐 gp.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black, new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);//小标题信息 left = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Left, true).Left - 2;//获取当前列的X坐标 if (left < 0) { left = this.GetCellDisplayRectangle(-1, -1, true).Width; } right = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Right, true).Right - 2;//获取当前列的Right if (right < 0) { right = this.Width; } //大标题 gp.DrawString(TableRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black, new Rectangle(left, top, right - left, (bottom - top) / 2), sf); e.Handled = true; } } base.OnCellPainting(e); } protected override void OnCellClick(DataGridViewCellEventArgs e)//在单元格中单击 { base.OnCellClick(e); } #region 二维表头的背景颜色 [Description("二维表头的背景颜色"),Browsable(true),Category("二维表头")]//在属性中显示这一栏 public Color ERBiaoTou { get{return _eRBiaoTou;} set{_eRBiaoTou = value;} } #endregion private Color _eRBiaoTou = System.Drawing.SystemColors.Window; #region 需要合并的列存入Dictionary #region 二维表头之表头信息 private Dictionary<int, TableTou> TableRows = new Dictionary<int, TableTou>();//需要二维表头的列 private struct TableTou//二维表头信息 { public TableTou(string Text, int Position, int Left, int Right) { this.Text = Text;//标题文本 this.Position = Position;//位置1左 2中 3右 this.Left = Left;//对应左边 this.Right = Right;//对应右边 } public string Text; public int Position; public int Left; public int Right; } #endregion #region 二维表头之合并列 /// <param name="ColIndex">列的索引</param> /// <param name="ColCount">需要合并的列数</param> /// <param name="Text">合并列后的文本</param> public void AddSpanHeader(int CoIindex, int CoICount, string Text)//合并列 { if (CoIindex < 2) { throw new Exception("行宽应大于等于2,合并1列无意义"); } else { //将小标题列加入大标题列中 int Right = CoIindex + CoICount - 1;//同一大标题下的最后一列的索引 TableRows[CoIindex] = new TableTou(Text, 1, CoIindex, Right);//添加标题下的最左列 TableRows[Right] = new TableTou(Text, 3, CoIindex, Right);//添加标题下的最右列 for (int i = CoIindex + 1; i < Right; i++) { TableRows[i] = new TableTou(Text, 2, CoIindex, Right);//添加标题下的中间列 } } } #endregion #endregion }}
调用窗体代码
#region 绑定数据源 dataGridView1.AutoGenerateColumns = false; dataGridView1.AutoSize = true; dataGridView1.DataSource = Table(); #endregion #region CheckBox列名 System.Windows.Forms.DataGridViewTextBoxColumn dgvcba = new DataGridViewTextBoxColumn();//登陆名列 dgvcba.HeaderText = "登录名"; dgvcba.Name = "columna"; dgvcba.ReadOnly = false; dgvcba.SortMode = DataGridViewColumnSortMode.Programmatic; this.dataGridView1.Columns.Insert(0, dgvcba); dgvcba.DataPropertyName = Table().Columns[0].ToString(); System.Windows.Forms.DataGridViewTextBoxColumn dgvcbb = new DataGridViewTextBoxColumn();//员工姓名列 dgvcbb.HeaderText = "员工姓名"; dgvcbb.Name = "columnb"; dgvcbb.ReadOnly = false; dgvcbb.SortMode = DataGridViewColumnSortMode.Programmatic; this.dataGridView1.Columns.Insert(1, dgvcbb); dgvcbb.DataPropertyName = Table().Columns[1].ToString(); //.......代码太长...... #endregion this.dataGridView1.Dock = DockStyle.Fill; this.dataGridView1.BackgroundColor = Color.White; this.dataGridView1.AllowUserToAddRows = true;//是否显示新行 this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.ColumnHeadersHeight = 40; this.dataGridView1.AddSpanHeader(2, 11, "员工享有权限");
1 0
- 自定义控件系列<第一篇>--多维表头
- 自定义控件系列<第二篇>--多维表头
- 自定义组件系列---第一篇
- 自定义控件之表头
- ORMLite系列---第一篇
- 控件测试第一篇
- mysql多维数据仓库指南-------第一篇第1章
- mysql多维数据仓库指南--第一篇第2章(1)
- mysql多维数据仓库指南--第一篇第2章(2)
- mysql多维数据仓库指南--第一篇第3章
- mysql多维数据仓库指南--第一篇第4章(1)
- mysql多维数据仓库指南--第一篇第4章(2)
- 多维表头应用效果图
- 多维表头的DataGridView
- DataGridView实现多维表头
- DataGridView实现多维表头
- 一篇学会自定义组合控件
- 钓鱼系列之第一篇
- Lock锁学习
- Programming In Scala笔记-第八章、函数与闭包
- Atitit.并发编程原理与概论 attilax总结
- 【Linux4.1.12源码分析】二层报文发送之GSO条件判断
- Java实现验证码(上)
- 自定义控件系列<第一篇>--多维表头
- 面向对象设计原则——单一职责原则(SRP)
- 泛型接口的使用
- Atitit.软件兼容性原理与实践 v3 q326.docx
- Ubuntu命令参考手册
- 小端模式 大端模式
- 面向对象设计原则--里氏替换原则(LSP)和依赖倒置原则(DIP)
- HDU 3068 最长回文(Manacher算法解决最长回文串问题)
- 后台开发学习——Servlet过滤器