开源DataGridView扩展(5) 简单实现统计行,有更好的方法吗?
一、需要吗?
我们的假设前提有一下:
1)你是一个Winform开发者。
2)你现在要用Grid实现你的需求。
3)你们项目组不准用三方控件。
4)你的需求中就偏偏需要对信息的统计。
如果你具备了上述的条件,那么你需要它。统计信息往往在表格中是比较重要的地位的,下面我们来看如何来实现:
二、能实现吗?
相对于其他的控件扩展,遇到这么个问题,我一开始真是无从下手;因为.Net的DataGridView本身就没有实现统计行,那么想扩展就找不到一个支点。
我简阅了很多的实现统计行的代码,有使用panel的有、有使用双DataGridView的;各式各样,不缺乏好的方案,但是我觉得唯一的缺憾就是他们都不来自DataGridView的自身扩展,也只能算个变通的实现方法。
经过我仔细的思考,既然没有现成的统计行,那么就利用Row来扩展,需要做到以下几点;
1)能实现统计行,添加统计信息;
2)统计行的单元格与表格保持一致,随着列宽的改变而改变,保持表格样式。
3)统计行要始终保持在最下方,不能随着排序等变动位置。
4)统计行的数据应该不跟一般的行一起获取。
先说说我的实现方法吧:
1. 先实现一个SummaryRow和SummaryCell
1: namespace DataGridViewEx.DataGridViewExs.RowEx2: {
3: /// <summary>4: /// 统计行5: /// </summary>6: public class DataGridSummaryRowEx:DataGridViewRow7: {
8:
9: }
10:
11: /// <summary>12: /// 统计单元格13: /// </summary>14: public class DataGridSummaryCellEx : DataGridViewTextBoxCell15: {
16: protected override void OnClick(DataGridViewCellEventArgs e)17: {
18:
19: //base.OnClick(e);20: }
21:
22: public override bool ReadOnly23: {
24: get
25: {
26: return true;27: }
28: set
29: {
30: base.ReadOnly = value;31: }
32: }
33: }
34: }
2. 在DataGridViewEx的CellPainting等事件中把SummaryCell过滤,不做处理。
1: protected override void OnCellFormatting(DataGridViewCellFormattingEventArgs e)2: {
3: if (this.Rows[e.RowIndex].Cells[e.ColumnIndex] is utGridSummaryCell)4: return;5: //Mark:在这里执行注册的程序6: this.CellFormatterRegister.RunFormatter(this.Columns[e.ColumnIndex].Name, e);7: //....8: }
3. 在 DataGridViewEx中的ColumnHeaderClick中处理,先Remove统计行,再添加统计行。(主要是解决排序的问题)
1: /// <summary>2: /// 在排序之前将统计行去除,使得排序不会根据统计行内容排序3: /// </summary>4: /// <param name="e"></param>5: protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)6: {
7: if (e.Button == System.Windows.Forms.MouseButtons.Left)8: this.RemoveSummaryRow();9: base.OnColumnHeaderMouseClick(e);10: if (e.Button == System.Windows.Forms.MouseButtons.Left)11: this.AppendSummaryRow();12: }
13:
14:
15: DataGridSummaryRowEx m_summaryRow = null;16:
17: private void RemoveSummaryRow()18: {
19: if (m_summaryRow == null) return;20: if (this.Rows.Contains(m_summaryRow))21: this.Rows.Remove(m_summaryRow);22: }
23:
24: private void AppendSummaryRow()25: {
26: if (m_summaryRow == null) return;27: this.RemoveSummaryRow();28: int index = this.Rows.Add(m_summaryRow);29: m_summaryRow = this.Rows[index] as DataGridSummaryRowEx;30: }
31:
32: /// <summary>33: /// 创建统计行,并且返回统计行对象,以便对单元格进行赋值信息34: /// </summary>35: /// <returns></returns>36: static Color m_summaryBackColor = Color.Linen;37: public DataGridSummaryRowEx CreateSummary()38: {
39: if (m_summaryRow == null)40: {
41: m_summaryRow = new DataGridSummaryRowEx();42:
43: //添加与column相同的列,只是这里的单元格是自扩展的。44: foreach (DataGridViewColumn col in this.Columns)45: {
46: m_summaryRow.Cells.Add(new DataGridSummaryCellEx());47: }
48: m_summaryRow.DefaultCellStyle.BackColor = m_summaryBackColor;
49: }
50: this.RemoveSummaryRow();51: this.AppendSummaryRow();52: return m_summaryRow;53: }
4. 看到那个CreateSummary 方法了吗,就是用这个方法添加的:
1: protected void IniailzieData()2: {
3: for (int i = 0; i < 10; i++)4: {
5: this.dataGridViewEx1.Rows.Add(new object[] {6: false,"测试文本"+i,"","btn"+i7: });
8: }
9:
10: DataGridSummaryRowEx summaryRow = this.dataGridViewEx1.CreateSummary(); 11: summaryRow.Cells[0].Value = "合计"; 12: summaryRow.Cells[2].Value = 122;13: }
三、有更好的方法吗?
先介绍一下我的实现原理吧:
1)设计一个CreateSummary方法在行尾添加一个统计行。
2)这个统计行,不使用DataGridView中的列信息,而是使用列数和列宽来使用SummaryCell来自定义一行。
3)这个统计行,在ColumnHeaderClick中先移除再添加,主要解决的是在排序之前把它移除,排序就不在内,然后添加到最后一行。
4)把这个行放出去,然后由外面来赋值,要实现自动统计还是比较麻烦的。
好了,介绍完我的实现方法,现求更好的方法,或者完善我的方法。
1) 我的方法中不能实现自动统计。
2) 我的方法中CreateSummary必须人为的在最后调用,所以不够安全。
3) 我的方法中使用枚举Rows时,也带了统计行信息。
由于有了这么多弊端,所以现求大牛们能否思考如果解决我的这些问题,或者能否有更好的实现思路。
四、源码及演示程序下载。
演示程序: 05[20120515]SummaryRow@DataGridViewEx.rar
开源项目:http://sourceforge.net/p/datagridviewex/code-0/3/tree/trunk/DataGridViewEx/
出处:http://gxjiang.cnblogs.com/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。