开源DataGridView扩展(5) 简单实现统计行,有更好的方法吗?

一、需要吗?

我们的假设前提有一下:

1)你是一个Winform开发者。

2)你现在要用Grid实现你的需求。

3)你们项目组不准用三方控件。

4)你的需求中就偏偏需要对信息的统计。

如果你具备了上述的条件,那么你需要它。统计信息往往在表格中是比较重要的地位的,下面我们来看如何来实现:

r0

二、能实现吗?

      相对于其他的控件扩展,遇到这么个问题,我一开始真是无从下手;因为.Net的DataGridView本身就没有实现统计行,那么想扩展就找不到一个支点。

      我简阅了很多的实现统计行的代码,有使用panel的有、有使用双DataGridView的;各式各样,不缺乏好的方案,但是我觉得唯一的缺憾就是他们都不来自DataGridView的自身扩展,也只能算个变通的实现方法。

      经过我仔细的思考,既然没有现成的统计行,那么就利用Row来扩展,需要做到以下几点;

     1)能实现统计行,添加统计信息;

     2)统计行的单元格与表格保持一致,随着列宽的改变而改变,保持表格样式。

     3)统计行要始终保持在最下方,不能随着排序等变动位置。

     4)统计行的数据应该不跟一般的行一起获取。

先说说我的实现方法吧:

1. 先实现一个SummaryRow和SummaryCell

   1:  namespace DataGridViewEx.DataGridViewExs.RowEx
   2:  {
   3:      /// <summary>
   4:      /// 统计行
   5:      /// </summary>
   6:      public class DataGridSummaryRowEx:DataGridViewRow
   7:      {
   8:           
   9:      }
  10:   
  11:      /// <summary>
  12:      /// 统计单元格
  13:      /// </summary>
  14:      public class DataGridSummaryCellEx : DataGridViewTextBoxCell
  15:      {
  16:          protected override void OnClick(DataGridViewCellEventArgs e)
  17:          {
  18:              
  19:              //base.OnClick(e);
  20:          }
  21:   
  22:          public override bool ReadOnly
  23:          {
  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"+i
   7:                  });
   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/

posted @ 2012-05-15 22:31  江心逐浪  阅读(5872)  评论(10编辑  收藏  举报