小菜的系统框架界面设计-数据的完美呈现(DataGridView扩展)
背景
今天在做系统报表的过程中,我想实现批量操作DataGridView中的数据,在列中加复选框,通过一个事件触发进行全选或取消,可是在外面添加按钮,这种模式虽然能够实现,但是从系统界面设计的角度,美观和灵活性就差很多了,能否在DataGridView头标题栏上呈现复选框,通过这个头标题复选框来对这一列的复选框,这样是不是更灵活,也美观一点?
问题
可是,找了半天,发现微软原始的DataGridView头标题栏没有CheckBox的功能,郁闷了~~
。
我在伍兄的博客找到有关于扩展DataGridVew在头标题栏添加全选功能按钮的功能(不是源码开源),而且他的这个程序集也不能满足我的需求,怎么办?
只有靠我自已去探索了,我在传统的DataGridView中实现了这个功能,但是整合进我的换肤组件中不能实现,Why? 我找了好友Strong一起研究,自已摸不清方向,最后还是他找到了问题点,可是却无法入手?(no any solution)
最后,经过自已的努力一步一步debug, 终于解决了问题,并整合进自已的换肤组件中,个人觉得有必要总结一下。
在总结技术点前,先展示一下我的成果,然后再做扩展说明,如下:
(图一)Office2007Blue效果

(图二) Office2007Silver效果

传统的解决方案
在传统的DataGridView上,实现基本上没有什么难处,只要按如下的步骤去操作就可以了。
添加一个DataGridViewColumnHeaderCellW.cs,继承DataGridViewColumnHeaderCell,
源码如下:
public class DataGridViewColumnHeaderCellW : DataGridViewColumnHeaderCell
{
public object HeaderTextDataSource { get; set; }
private Type _dataSourceType = null;
public Type DataSourceType
{
get
{
if (HeaderTextDataSource != null && _dataSourceType == null)
_dataSourceType = HeaderTextDataSource.GetType();
return _dataSourceType;
}
set { _dataSourceType = value; }
}
public string FieldName { get; set; }
public string Prefix { get; set; }
public string Suffix { get; set; } Point checkBoxLocation;
Size checkBoxSize;
bool _checked = false;
Point _cellLocation = new Point();
System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
public event datagridviewcheckboxHeaderEventHander OnCheckBoxClicked;
//绘制列头checkbox
protected override void Paint(System.Drawing.Graphics graphics,
System.Drawing.Rectangle clipBounds,
System.Drawing.Rectangle cellBounds,
int rowIndex,
DataGridViewElementStates dataGridViewElementState,
object value,
object formattedValue,
string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex,
dataGridViewElementState, value,
formattedValue, errorText, cellStyle,
advancedBorderStyle, paintParts);
Point p = new Point();
Size s = CheckBoxRenderer.GetGlyphSize(graphics,
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
p.X = cellBounds.Location.X +
(cellBounds.Width / ) - (s.Width / ) - ; //列头checkbox的X坐标
p.Y = cellBounds.Location.Y +
(cellBounds.Height / ) - (s.Height / ); //列头checkbox的Y坐标
_cellLocation = cellBounds.Location;
checkBoxLocation = p;
checkBoxSize = s;
if (_checked)
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.CheckedNormal;
else
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.UncheckedNormal;
CheckBoxRenderer.DrawCheckBox
(graphics, checkBoxLocation, _cbState);
} /// <summary>
/// 点击列头checkbox单击事件
/// </summary>
protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
{ Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
if (p.X >= checkBoxLocation.X && p.X <=
checkBoxLocation.X + checkBoxSize.Width
&& p.Y >= checkBoxLocation.Y && p.Y <=
checkBoxLocation.Y + checkBoxSize.Height)
{
_checked = !_checked; //获取列头checkbox的选择状态
datagridviewCheckboxHeaderEventArgs ex = new datagridviewCheckboxHeaderEventArgs();
ex.CheckedState = _checked; object sender = new object();//此处不代表选择的列头checkbox,只是作为参数传递。应该列头checkbox是绘制出来的,无法获得它的实例 if (OnCheckBoxClicked != null)
{
OnCheckBoxClicked(sender, ex);//触发单击事件
this.DataGridView.InvalidateCell(this); } }
base.OnMouseClick(e);
}
在DataGridViewColumnHeaderCellW.cs内部,添加一个委托和继承EventArgs事件数据的基类:
public delegate void datagridviewcheckboxHeaderEventHander(object sender, datagridviewCheckboxHeaderEventArgs e);
//定义包含列头checkbox选择状态的参数类
public class datagridviewCheckboxHeaderEventArgs : EventArgs
{
private bool checkedState = false;
public bool CheckedState
{
get { return checkedState; }
set { checkedState = value; }
}
}
如何调用?
先在界面上添加一个DataGridView,并添加一列,选类型为DataGridViewCheckBoxColumn,在Form_Load事件中添加如下代码:
private void Form1_Load(object sender, EventArgs e)
{
DataGridViewColumnHeaderCellW ch = new DataGridViewColumnHeaderCellW();
ch.OnCheckBoxClicked += new datagridviewcheckboxHeaderEventHander(OnCheckBoxClicked);
//第三列为DataGridViewCheckBoxColumn
DataGridViewCheckBoxColumn checkboxCol = this.dataGridView1.Columns[] as DataGridViewCheckBoxColumn;
checkboxCol.HeaderCell = ch;
checkboxCol.HeaderCell.Value = string.Empty;//消除列头checkbox旁出现的文字
}
没题解决了!
展示一下,这个复选框暂放在最后一列,如下图:

这个真是灰头土脸,像是灰姑娘那么丑。
于是,我整合进我的换肤中,可是怎么也不能实现,标题栏就是不出来,结果成了如下图这样子:

最后经过一系列努力,定位问题在CellPainting事件中,重绘的过程把标题栏的checkbox效果覆盖了。
我在此事件中添加如下代码:
if (e.RowIndex == -)
{
if (!(_columnHeaderUpColor == Color.Transparent) && !(_columnHeaderDownColor == Color.Transparent) &&
!_columnHeaderUpColor.IsEmpty && !_columnHeaderDownColor.IsEmpty)
{
DrawLinearGradient(e.CellBounds, e.Graphics, _columnHeaderUpColor, _columnHeaderDownColor);
if (ShowColumnHeaderCheckBox)
{
e.Paint(e.ClipBounds, (DataGridViewPaintParts.All & ~DataGridViewPaintParts.Background));
}
else
{
DrawText(e);
}
e.Handled = true;
}
}
问题终于解决,但是在代码中为什么用ShowColumnHeaderCheckBox?
并不是所有的数据呈现功能都要有这个头标题栏复选框的功能,为了更好的兼容性,我在添加了这个属性,开发人员可以通过此属性灵活选择,默认是false。
public bool showColumnHeaderCheckBox;
public bool ShowColumnHeaderCheckBox
{
get
{
return showColumnHeaderCheckBox;
}
set { showColumnHeaderCheckBox = value; }
}
在客户端这样去设就可以了。
private void Form1_Load(object sender, EventArgs e)
{
InitParameterList();
dataGridView1.ShowColumnHeaderCheckBox = true;//此处设为true
DataGridViewColumnHeaderCellW ch = new DataGridViewColumnHeaderCellW();
ch.OnCheckBoxClicked += new datagridviewcheckboxHeaderEventHander(OnCheckBoxClicked);
//第三列为DataGridViewCheckBoxColumn
DataGridViewCheckBoxColumn checkboxCol = this.dataGridView1.Columns[] as DataGridViewCheckBoxColumn;
checkboxCol.HeaderCell = ch;
checkboxCol.HeaderCell.Value = string.Empty;//消除列头checkbox旁出现的文字
}
总结
在研究一个新的东西时,我一般是先实现粗糙的功能,由浅入深渐渐细化这么一个演变的过程,毕竟灰姑娘一下要变成白雪公主也是要有个过程的。
元芳,你怎么看?
小菜的系统框架界面设计-数据的完美呈现(DataGridView扩展)的更多相关文章
- 小菜的系统框架界面设计-XiaoCai.WinformUI代码开源
我的源码分享 曾经,看到别人漂亮的系统界面,合理的布局,可是却没有提供源码,道理很简单,就是有偿提供,实际上对于有些技巧的东西也并没有多么难,只是不懂原理,感觉到困难罢了. 而对于刚毕业的我,求知欲强 ...
- 小菜的系统框架界面设计-灰姑娘到白雪公主的蜕变(工具条OutLookBar)
灰姑娘本身也有自已的优点,但是却可能因为外貌不讨人喜欢,要变成白雪公主却需要有很多勇气和决心去改变自已: 有一颗善良的心 讨人喜爱的外貌 --蜕变--> 我这里讲的是一个工具条的蜕变过程, ...
- Java日志系统框架的设计与实现
推荐一篇好的文章介绍java日志系统框架的设计的文章:http://soft.chinabyte.com/database/438/11321938.shtml 文章内容总结: 日志系统对跟踪调试.程 ...
- 基于Hadoop开发网络云盘系统客户端界面设计初稿
基于Hadoop开发网络云盘系统客户端界面设计初稿 前言: 本文是<基于Hadoop开发网络云盘系统架构设计方案>的第二篇,针对界面原型原本考虑有两个方案:1.类windows模式,文件夹 ...
- Winform XiaoCai.WinformUI 框架界面设计
开源用户界面和布局的套件XiaoCai.WinformUI(美化用户界面利器) http://www.cnblogs.com/aganqin/p/3400453.html 源码下载:https://g ...
- 苹果IOS与谷歌 android系统的UI设计原则
一.苹果为IOS的界面设计提出了六大原则: 1.整体美学 整体美学指的是一个应用的表现和行为与它的功能完美集成,传达连贯的信息. 人们关心一个应用是否提供它承诺的功能,但他们也被应用的外观和行为强烈影 ...
- [自制操作系统] BMP格式文件读取&图形界面系统框架/应用接口设计
本文将介绍在本人JOS中实现的简单图形界面应用程序接口,应用程序启动器,以及一些利用了图形界面的示例应用程序. 本文主要涉及以下部分: 内核/用户RW/RW调色板framebuffer共享区域 8bi ...
- [课程设计]Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化)
Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅 ...
- 基于WPF系统框架设计(3)-Fluent Ribbon界面布局
一个系统框架除了功能菜单导航,有系统内容显示区域,系统状态栏. Silver: Blue: Black: 系统界面设计,就不进行技术细节介绍了,主题以框架设计为主,Xaml源码参考: <Flue ...
随机推荐
- java枚举使用
1.开发中如何使用枚举,一般在开发中使用消息提示.枚举可以继承,实现接口等.public enum Result { SUCCESS(1,"201 ok") { @Override ...
- 在iis中注册.net framework
首先定位到文件夹:cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 执行命令:aspnet_regiis.exe -i
- css3实现小米商城鼠标移动图片上浮阴影效果
今天在编程爱好者编码库看见一个好玩的程序,代码如下. <!DOCTYPE html> <html> <head> <meta charset=&quo ...
- Android开发-API指南-应用程序开发基础
Application Fundamentals 英文原文:http://developer.android.com/guide/components/fundamentals.html 采集(更新) ...
- Decks
Now that we have Card objects, the next step is to define a class to represent decks. Since a deck i ...
- socket学习笔记——select函数的使用(windows)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h ...
- ORA-12518,TNS:listener could not hand off client connection
前几天在启动应用的时候,在控制台抛出了此异常信息!很明显是数据库方面的问题,不过具体是什么问题哪?百度了一下,网上关于此问题的信息还是有比较多,从异常的提示中我们也能看到是具体是和客户端的连接相关的问 ...
- WebService之基于REST机制的实现实例(Java版)
REST是REpresentational State Transfer的缩写(一般中文翻译为表述性状态转移).2000年Roy Fielding博士在他的博士论文“Architectural Sty ...
- Digest [IAB_SRI_Online_Advertising_Effectiveness]
http://www.pwc.com/en_GX/gx/entertainment-media/pdf/IAB_SRI_Online_Advertising_Effectiveness_v3.pdf
- prototype原型模式中的问题
对于每个构造函数来说,都有一个prototype属性.对于每个对象实例来说,都有_proto_属性. 参看下面代码: function Person(){} Person.prototype={ na ...