转贴:girdview分组,统计,排序的解决方案
转自:http://hi.baidu.com/sneer_owen/blog/item/ec85e0df164d4651cdbf1a02.html
导言:
GridView 控件与 DataGrid 相比有了很大的改进,但仍不够完美,比如进行分组(group)和统计(summary).为了实现统计功能,我们可以在 RowDataBound 事件里进行编码;而分组则要复杂一些。如果同时实现这2种功能就更棘手了,基于这个难题我们可以考虑使用 GridViewHelper 类,就像其名称一样,它的用处在于构建分组和统计.
使用 GridViewHelper
下面我们将看一些 GridViewHelper 的示例.首先我们展示 groups 和 summaries 创建的方格.该示例的数据来自 Northwind 数据库,做了些许修改:
图1
要为 ItemTotal 列创建统计功能,我只需要2行代码:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum);
}
首先,我们创建 GridViewHelper,然后对指定的列注册 summary 功能,那么就可以执行 summary 操作了,结果如下图所示.
图2:
在该示例里,最下面新添加了一行以显示统计结果.不过,我们也可以在页脚行显示统计结果,而用不着新添加一行.不同的是,新添加一行时,只生成一个单元格来显示结果,而在页脚行显示时,所有的单元格都会显示出来.
现在我们来创建分组,代码如下:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterGroup("ShipRegion", true, true);
helper.ApplyGroupSort();
}
其中,RegisterGroup 方法的第一个参数定义了分组依据,也就是按哪个列来进行分组.当然也可以创建交叉分组(composite group),也就是按照几个列的组合进行分组.第二个参数指定了是否自动分组,就本例而言,为每个组的标头新创建一行.第三个参数指定是否把作为分组依据的那个列强制隐藏.而 ApplyGroupSort 方法将分组依据的那个列作为排序标准(sort expression),就本例而言,自然就是 ShipRegion 了.这么做是很有必要的,因为有可能数据从数据库检索来时已经进行了某种排序.如下图,ShipRegion 列已经被隐藏了:
图3
让我们来看一些更有趣的事情,向各个分组添加统计功能.如下:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterGroup("ShipRegion", true, true);
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipRegion");
helper.ApplyGroupSort();
}
这次,RegisterSummary 方法多了一个参数。该参数指定了创建统计功能的组的名称。组的名称自动由作为分组依据的那些列的名字生成.如果分组依据只有一个列,那么组的名称就是那一列的名称;如果分组依据有多个列,那么组名由这些列名按顺序串联起来,用加号("+")连接,如"ShipRegion+ShipName".下图为进行了分组且对每组添加统计功能的情况:
图4
我们还可以创建"等级组",如下所示:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterGroup("ShipRegion", true, true);
helper.RegisterGroup("ShipName", true, true);
helper.ApplyGroupSort();
}
结果如下:
图5
GridViewHelper 有一些事件可以很容易的实现视觉或功能上的调整,如下:
图6:
GroupStart:当新的分组开始时发生,意思就是说,当在作为分组依据的列里发现新的值时.
GroupEnd:某个组的最后一行结束时发生.
GroupHeader:当自动的为某个组添加一个标头时发生.如果不是自动的分组的话将不会触发该事件.
GroupSummary:当为某个组生成统计功能时发生。如果不是自动分组的话将不会触发该事件,不过分组类型是 suppression group(我们将在后面介绍)的话,另当别论.
GeneralSummary:当算出最终累计数时发生.如果最终累计数是自动生成的,那么在添加统计行,且数字填充到行之后才触发该事件.
通过寥寥几行代码我们就可以改善界面,如下:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterGroup("ShipRegion", true, true);
helper.RegisterGroup("ShipName", true, true);
helper.GroupHeader += new GroupEvent(helper_GroupHeader);
helper.ApplyGroupSort();
}
private void helper_GroupHeader(string groupName, object[] values, GridViewRow row)
{
if ( groupName == "ShipRegion" )
{
row.BackColor = Color.LightGray;
row.Cells[0].Text = " " + row.Cells[0].Text;
}
else if (groupName == "ShipName")
{
row.BackColor = Color.FromArgb(236, 236, 236);
row.Cells[0].Text = " " + row.Cells[0].Text;
}
}
改善后的界面如下:
图7:
更多分组选项
这里还有2个案例。第一个是交叉分组(composite group).第二个案例定义了一个 suppress group,其行为与 sql GROUP BY 字句一样,重复的值都过滤掉,且将summary操作建立在其它列的基础上.
下面我们将看到这些交叉组的代码以及界面:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
string[] cols = new string[2];
cols[0] = "ShipRegion";
cols[1] = "ShipName";
helper.RegisterGroup(cols, true, true);
helper.ApplyGroupSort();
}
图8
我们可以向该分组添加统计功能.这次,我们将定义一个求平均数的操作,并添加一个显示该操作的label控件:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
string[] cols = new string[2];
cols[0] = "ShipRegion";
cols[1] = "ShipName";
helper.RegisterGroup(cols, true, true);
helper.RegisterSummary("ItemTotal", SummaryOperation.Avg, "ShipRegion+ShipName");
helper.GroupSummary += new GroupEvent(helper_GroupSummary);
helper.ApplyGroupSort();
}
private void helper_GroupSummary(string groupName, object[] values, GridViewRow row)
{
row.Cells[0].HorizontalAlign = HorizontalAlign.Right;
row.Cells[0].Text = "Average";
}
图9:
最后这个示例将创建一个 suppress group.有一点很重要,如果定义了一个 suppress group 就不能创建其它的分组.同理,如果已经一个分组,也不能再定义一个 suppress group,如果你非要硬来的话将抛出一个异常.
下面我们将看到 suppress group 的代码以及界面:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.SetSuppressGroup("ShipName");
helper.RegisterSummary("Quantity", SummaryOperation.Sum, "ShipName");
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
helper.ApplyGroupSort();
}
图10
那些没有在 summary 操作里定义的列,其包含的值没有显示出来.它提示某种信息:
"Column 'column_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
没有必要将那些无关的列显示出来。为此,我们调用一个方法将它们隐藏起来:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.SetSuppressGroup(rdBtnLstGroup.SelectedValue);
helper.RegisterSummary("Quantity", SummaryOperation.Sum, "ShipName");
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
helper.SetInvisibleColumnsWithoutGroupSummary();
helper.ApplyGroupSort();
}
结果如下:
图11
Summary 操作
GridViewHelper 有3个内置的统计操作:sum, average 以及 row count.我们可以定制自己的统计操作.为此,我们要为 GridViewHelper 提供2个方法.第一个方法将会被方格(或组)里的每一行所调用,第二个方法将会被调用来返回结果.下面我们将展示一个用户自定义统计操作的示例.其返回最小值:
private List<int> mQuantities = new List<int>();
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterSummary("Quantity", SaveQuantity, GetMinQuantity);
}
private void SaveQuantity(string column, string group, object value)
{
mQuantities.Add(Convert.ToInt32(value));
}
private object GetMinQuantity(string column, string group)
{
int[] qArray = new int[mQuantities.Count];
mQuantities.CopyTo(qArray);
Array.Sort(qArray);
return qArray[0];
}
在上面的代码中,2个方法都接受 group 和 column 名称.如果统计方法不涉及到 group,那么该参数为 null.这些方法都被每一行所调用,同时接受当前行的某列的值.最终效果如下:
图12
局限性
在上面的例子我们模拟(simulate)了一个"等级组"。虽然该方格看起来具有"层次感",但执行起来绝不会按层次进行.没有group 或 subgroup,只有 sequentially registered groups.不过,如果我们想对一个内镶组添加统计功能时,这倒是个问题.下面,我们将看在这种情况下将会发生什么情况:
protected void Page_Load(object sender, EventArgs e)
{
GridViewHelper helper = new GridViewHelper(this.GridView1);
helper.RegisterGroup("ShipRegion", true, true);
helper.RegisterGroup("ShipName", true, true);
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
helper.RegisterSummary("ItemTotal", SummaryOperation.Sum);
helper.GroupSummary += new GroupEvent(helper_Bug);
helper.ApplyGroupSort();
}
private void helper_Bug(string groupName, object[] values, GridViewRow row)
{
if (groupName == null) return;
row.BackColor = Color.Bisque;
row.Cells[0].HorizontalAlign = HorizontalAlign.Center;
row.Cells[0].Text = "[ Summary for " + groupName + " " + values[0] + " ]";
}
图13
如上图所示,summary 在外部组(outer group)的标头创建后再创建.原因是,本来事件的发生顺序是:
Group1_Start
Group1_End
Group2_Start
Group2_End
对 hierarchical grouping 而言,事件发生顺序为:
Group1_Start
Group2_Start
Group2_End
Group1_End
贯彻
GridViewHelper 是作为一个独立类(standalone class)而不是继承类来贯彻的,这就使的利用GridViewHelper 来处理任何的 GridView 成为了可能。另外还有4个类:GridViewSummary, GridViewGroup, GridViewSummaryList 以及 GridViewGroupList.这些"list" classes 可以利用一个字符串索引来进行访问,如:
helper.GeneralSummaries["ItemTotal"].Value.
当创建 GridViewHelper 时,将对目标 GridView 的一个引用进行保存,且 RowDataBound 事件将绑定到一个方法完成实际的工作:
public GridViewHelper(GridView grd, bool useFooterForGeneralSummaries, SortDirection groupSortDirection)
{
this.mGrid = grd;
this.useFooter = useFooterForGeneralSummaries;
this.groupSortDir = groupSortDirection;
this.mGeneralSummaries = new GridViewSummaryList();
this.mGroups = new GridViewGroupList();
this.mGrid.RowDataBound += new GridViewRowEventHandler(RowDataBoundHandler);
}
GridViewHelper 内部使用的一些方法被定义为 public,因为如果必要的话可以将这些有用的方法进行用户定制.还有一些其它的操作选择没有在示例里进行演示,不过我们可以通过 Visual Studio 的智能感知系统来查证.
纪要:
对值类型的过多的的装箱和拆箱操作会对执行性能产生影响.为此,我们可以用泛型来贯彻这些内置的统计操作,但这并没有想象的那么容易,可以参阅文章《Using Generics for Calculations》或《Operator Overloading with Generics》。在现实生活中,这种影响不太显著,除非有数百万行,或有数千个用户分组,且同时进行数据统计操作.
在线案例将 GridView 的 EnableViewState 设置为 false. 这是必要的,因为当其为true,在一个页面回传时,GridView 控件将从 ViewState 进行重新绑定,而不会触发 RowDataBound 事件.我们可以在 ASP.Net 2.0里放心的禁用该 ViewState,因为 ControlState 仍然进行了保存.
转自:http://hi.baidu.com/sneer_owen/blog/item/ec85e0df164d4651cdbf1a02.html
示例代码http://www.agrinei.com/gridviewhelper/gridviewhelpersample_en.zip
转载于:https://www.cnblogs.com/DonaldTang/archive/2010/03/17/1687878.html
转贴:girdview分组,统计,排序的解决方案相关推荐
- MySQL连表分组统计使用count查询出数据不准确问题解决方案
先上两副图 这里有两张表:score表和year_as表,要求统计出score表按年份分组的个数,且查询出来的内容需要包括year_as表中的year_as字段. 使用正常连表并分组统计count得出 ...
- SQL service基础(二)对数据指定列查询、条件查询、查询结果排序、聚集函数查询、分组统计查询
实验目标: 1.掌握指定列或全部列查询 2.掌握按条件查询 3.掌握对查询结果排序 4.掌握使用聚集函数的查询 5.掌握分组统计查询 一.请完成书中实验7.1,并完成以下问题. 1.查询所有学生的姓名 ...
- Java 8 辣么大(lambda)表达式不慌之—–(五)示例-Collectors中的统计、分组、排序等
Java 8 辣么大(lambda)表达式不慌之-–(五)示例-Collectors中的统计.分组.排序等 summarizingInt 按int类型统计 maxBy取最大/minBy取最小 aver ...
- MongoDb数组操作 - unwind解包、group分组统计、sort排序
MongoDB统计文档(Document)的数组(Array)中的各个元素出现的次数 一,问题描述 [使用 unwind 操作符 "解包" Document 里面的Array中的每 ...
- es统计有多少个分组_ES 24 - 如何通过Elasticsearch进行聚合检索 (分组统计)
1 普通聚合分析 1.1 直接聚合统计 (1) 计算每个tag下的文档数量, 请求语法: GET book_shop/it_book/_search { "size": 0, // ...
- 编写MapReduce程序,统计每个买家收藏商品数量,实现统计排序功能
实验材料及说明 在Ubuntu系统的/学号(每个人用自己的学号)/salesInfo目录下,有买家的购买记录文件Sales,该文件记录了买家的id,购买商品的id以及购买日期,文件为名为Sales.S ...
- ROW_NUMBER() OVER()函数用法;(分组,排序),partition by
1.row_number() over()排序功能: (1) row_number() over()分组排序功能: 在使用 row_number() over()函数时候,over()里头的分组以及排 ...
- 问题 B: 分组统计
分组统计 问题 B: 分组统计时间限制: 1 Sec 内存限制: 32 MB 提交: 416 解决: 107 [提交][状态][讨论版][命题人:外部导入] 题目描述 先输入一组数,然后输入其分组,按 ...
- asc desc排序_HIVE的学习之路(六)Hive的分组Join排序
分组 Group By语句 GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作. 案例实操: (1)计算emp表每个部门的平均工资 hive (d ...
- mongodb按照时间分组统计
使用spring data mongodb v1.8 需求1. 数据结构如下.说明:改集合记录的是公司各个系统的访问情况(localPath表示系统,requestTime 表示请求时间,字符串类型, ...
最新文章
- 【Smart_Point】unique_ptr中独占指针使用MakeFrame
- swoole 异步redis
- 一个孩子能长大成人到底有多不容易? | 今日最佳
- 潘在亮:给业务开发提供黑科技装备的“测试Q博士”
- 向Excle中插入多个表
- python 前端开发_python和前端开发怎么抉择?
- IntelliJ IDEA 下载安装以及破解码大集合
- GitLab 创建项目组及将代码导入项目
- android netd firewall 分析,第2章 深入理解Netd
- 【社招】量化研究员(机器学习)-Akuna Capital -上海
- 西门子博图功能指令(移动块)
- Android组件化开发实践和案例分享 1
- 利用R语言对泰坦尼克号沉没事件幸存者的数据分析与预测
- 腾讯云的服务器解析域名步骤
- 数学建模实战9(聚类分析)
- 智能文档控制——文档的智能归档、捕获、索引、访问和协作
- Python Web前端实战案例——电商网站商品菜单导航栏
- 人脸识别论文:Partial FC: Training 10 Million Identities on a Single Machine
- python 之Entry
- ORAN专题系列-16:5G O-RAN FrontHaul前传接口的网络配置管理协议netconf
热门文章
- 微信启动界面:张小龙的情怀和马化腾的爱好
- VB.net MessageBox弹出的确认对话框点击确定按钮
- 松翰SN8F5703单片机WDT例程
- sql server查询不显示结果_仅凭网上查询结果显示邮件由行政机关签收,能证明行政机关一定收到了当事人的申请吗?...
- 基于遗传算法优化的BP神经网络算法
- 移动常见业务单词和词组
- Unity VFX学习系列 —— Operators 详细说明
- linux rd类型文件,RD 文件扩展名: 它是什么以及如何打开它?
- 潭州学院html学习(day02)
- 怎么修改服务器文件写入权限,怎么修改服务器本地写入权限设置