背景

今天在做系统报表的过程中,我想实现批量操作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扩展)的更多相关文章

  1. 小菜的系统框架界面设计-XiaoCai.WinformUI代码开源

    我的源码分享 曾经,看到别人漂亮的系统界面,合理的布局,可是却没有提供源码,道理很简单,就是有偿提供,实际上对于有些技巧的东西也并没有多么难,只是不懂原理,感觉到困难罢了. 而对于刚毕业的我,求知欲强 ...

  2. 小菜的系统框架界面设计-灰姑娘到白雪公主的蜕变(工具条OutLookBar)

    灰姑娘本身也有自已的优点,但是却可能因为外貌不讨人喜欢,要变成白雪公主却需要有很多勇气和决心去改变自已: 有一颗善良的心 讨人喜爱的外貌   --蜕变-->  我这里讲的是一个工具条的蜕变过程, ...

  3. Java日志系统框架的设计与实现

    推荐一篇好的文章介绍java日志系统框架的设计的文章:http://soft.chinabyte.com/database/438/11321938.shtml 文章内容总结: 日志系统对跟踪调试.程 ...

  4. 基于Hadoop开发网络云盘系统客户端界面设计初稿

    基于Hadoop开发网络云盘系统客户端界面设计初稿 前言: 本文是<基于Hadoop开发网络云盘系统架构设计方案>的第二篇,针对界面原型原本考虑有两个方案:1.类windows模式,文件夹 ...

  5. Winform XiaoCai.WinformUI 框架界面设计

    开源用户界面和布局的套件XiaoCai.WinformUI(美化用户界面利器) http://www.cnblogs.com/aganqin/p/3400453.html 源码下载:https://g ...

  6. 苹果IOS与谷歌 android系统的UI设计原则

    一.苹果为IOS的界面设计提出了六大原则: 1.整体美学 整体美学指的是一个应用的表现和行为与它的功能完美集成,传达连贯的信息. 人们关心一个应用是否提供它承诺的功能,但他们也被应用的外观和行为强烈影 ...

  7. [自制操作系统] BMP格式文件读取&图形界面系统框架/应用接口设计

    本文将介绍在本人JOS中实现的简单图形界面应用程序接口,应用程序启动器,以及一些利用了图形界面的示例应用程序. 本文主要涉及以下部分: 内核/用户RW/RW调色板framebuffer共享区域 8bi ...

  8. [课程设计]Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化)

    Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅 ...

  9. 基于WPF系统框架设计(3)-Fluent Ribbon界面布局

    一个系统框架除了功能菜单导航,有系统内容显示区域,系统状态栏. Silver: Blue: Black: 系统界面设计,就不进行技术细节介绍了,主题以框架设计为主,Xaml源码参考: <Flue ...

随机推荐

  1. spring错误:<context:property-placeholder>:Could not resolve placeholder XXX in string value XXX

    spring同时集成redis和mongodb时遇到多个资源文件加载的问题 这两天平台中集成redis和mongodb遇到一个问题 单独集成redis和单独集成mongodb时都可以正常启动程序,但是 ...

  2. Excel粘贴到textarea换行符替换

    复制到→ Excel列表的内容复制到textarea中后,前台取到的文本是这样的: chrome监视显示 console.log输出 现在需要将excel中的每行数据拼接起来用“;”隔开,方法如下: ...

  3. android studio 更新 Gradle错误解决方法

    Android Studio每次更新版本都会更新Gradle这个插件,但由于长城的问题每次更新都是失败,又是停止在Refreshing Gradle Project ,有时新建项目的时候报 Gradl ...

  4. threading event

    #!usr/bin/env python 2 #coding: utf-8 3 #Author: Andy 4 5 import threading 6 import time 7 8 def pro ...

  5. 《Code Complete》ch.29 集成

    WHAT? 集成是这样一种软件开发行为:将一些独立的软件组合为一个完整的系统. WHY? 更容易诊断缺陷 尽早获得一个可工作的产品 更好的顾客关系 增强士气 更可靠地估计进度表 更准确的现状报告 HO ...

  6. dedecms首页怎么调用公司简介的内容

    DeDeCMS功能虽然强大,但还是有些细节上的功能没有实现,正如本文描述的问题一样,DEDECMS要在网站首页调用公司简介的内容,而且还要截取前多少个字符数的时候,DEDECMS标签中没有能实现这样的 ...

  7. 从AlphaGo谈通用型人工智能设计

    最近赢了人机大战的AlphaGo火了,火得一塌糊涂,圈里圈外,是人都在谈AlphaGo.但是AlphaGo毕竟是为特定场景特定应用设计的特定型人工智能,和通用型人工智能还是有很大差别,离人工智能普及更 ...

  8. 高校应该使用 Drupal 的10大理由

    使用 Drupal 已经成为全球顶尖高校中的一种潮流,它已经被全球数以百计的院校选择并应用,无论是哈佛.斯坦福.杜克.布朗.罗格斯.剑桥.耶鲁还是其它众多知名高校,都已经选择 Drupal 作为它们理 ...

  9. 集群监控系统Ganglia应用案例

    集群监控系统Ganglia应用案例 --我们把集群系统投入生产环境后,这时就需要一套可视化的工具来监视集群系统,这将有助于我们迅速地了解机群的整体配置情况,准确地把握机群各个监控节点的信息,全面地察看 ...

  10. 【Python】django安装

    官方下载:https://www.djangoproject.com/download/ 报错 [root@test Django-]# python setup.py install Traceba ...