65.9K
CodeProject 正在变化。 阅读更多。
Home

汇总 DataGridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (26投票s)

2010年1月12日

CPOL

4分钟阅读

viewsIcon

209763

downloadIcon

34993

带有附加 SummaryRow 的 DataGridView

Article_1.gif

引言

在开发基于 Windows 窗体的客户端-服务器应用程序时,我一直在寻找一个 DataGridView 组件,它能够显示列内容的数字聚合。例如:对 Grid 中一列显示的客户订单中的项目总数进行求和。就像 Excel 可以做的那样。我没有找到合适的解决方案,所以我决定开发自己的组件。它应该像 DataGridView 一样工作,并具有在 Grid 底部显示一行的能力。

为了重新定位和调整 SummaryRow 的大小,我重构了一些代码,这些代码取自 Robert Rhode 的优秀的 Filterable DataGrid:gridextensions.aspx。非常感谢他的出色工作。

入门

要使用 SummaryDataGridViewTest 应用程序,您必须将 Nwind.mdb 数据库复制到输出目录。

背景

对 DataGridView 和 Window-Forms 库的良好了解有助于自定义代码,但这不是必需的。 SummaryDataGridView 的使用非常简单。

Using the Code

SummaryDataGridView 控件可以像 Windows 窗体的任何其他控件一样使用,并支持设计时配置。它在设计器中有一组可用的公共属性。它的使用与 DataGridView 非常相似,因为它派生自它。要显示数据,请设置控件的 DataSource 属性。要汇总的每列都必须添加到字符串数组 SummaryColumns 中。 有关公共属性以及它们如何影响 SummaryDataGridView,请参见图 1 和图 2。

Article_3.gif

图 SEQ 图 \* ARABIC 1

Article_2.gif

图 SEQ 图 \* ARABIC 2

SummaryRow

将 DataGridView 的一行用作 SummaryRow 非常棘手,并带来一些问题。我没有找到将 SummaryRow 锁定在网格底部的解决方案,这对于滚动是必需的。因此,我决定使用一个带有文本框的简单控件,该控件显示在 DataGridView 下方。所有 TextBoxes 都以 DataGridView 相同的方式调整大小。此外,有必要绘制自己的水平滚动条,该滚动条将显示在我们的 SummaryControlContainer 下方,而不是使用 DataGridView 的 h 滚动条,该滚动条将显示在我们的 SummaryRow 的**上方**。 因此,很大一部分代码用于定位、调整大小和重新排序我们的 SummaryRow。 对一行中的值求和是控件最简单的部分。 处理以下 DataGridView 事件以将 SummaryRow 与 DataGridView 同步

ColumnAdded、ColumnRemoved、ColumnStateChanged、ColumnDisplayIndexChanged

有关同步的更多信息,请查看 SummaryControlContainer 类的 reCreateSumBoxes()resizeSumBoxes() 方法。

SummaryRow 和 DataGridView 之间的粘合剂

一个问题是如何将 SummaryRow 附加到 DataGridView。 最简单的方法是使用 Control,然后将 DataGridView 和 SummaryRow 包含在其中。 可以通过公共属性访问内部网格。 我决定让 DataGridView 创建自己的 SummaryRow。 为了避免设计器出现问题,这仅在运行时完成。 初始化后,DataGridView 调用 ChangeParent() 方法。 此方法从其父级删除 DataGridView,在其位置创建一个面板,然后将 DataGridView 和 SummaryRow 包含在面板中。 对于 TableLayoutPanel,我们必须在删除 DataGridView 之前确定其确切位置。

       private void changeParent()
       {
           if (!DesignMode && Parent != null)
          {

             [..]
               panel.Bounds = this.Bounds;
               panel.BackColor = this.BackgroundColor;                                     
               panel.Dock = this.Dock;
               [..]

               summaryControl.Dock = DockStyle.Bottom;
               this.Dock = DockStyle.Fill;                

   
   Special handling for TableLayoutPanels
            if (this.Parent is TableLayoutPanel)
            {
                int rowSpan, colSpan;

                TableLayoutPanel tlp = this.Parent as TableLayoutPanel;                   
                TableLayoutPanelCellPosition cellPos = 
                tlp.GetCellPosition(this);

                rowSpan = tlp.GetRowSpan(this);
                colSpan = tlp.GetColumnSpan(this);

                tlp.Controls.Remove(this);
                tlp.Controls.Add(panel, cellPos.Column, cellPos.Row);
                tlp.SetRowSpan(panel, rowSpan);
                tlp.SetColumnSpan(panel, colSpan);

              }
              else
              {
                  Control parent = this.Parent;

                  remove DataGridView from ParentControls
                  parent.Controls.Remove(this);
                  parent.Controls.Add(panel);                    
              }

              summaryControl.Controls.Add(hScrollBar);
              hScrollBar.BringToFront();
              panel.Controls.Add(this);
              panel.Controls.Add(summaryControl);

              adjustSumControlToGrid();
              adjustScrollbarToSummaryControl();
              resizeHScrollBar();                
          }
      }

只读 TextBox

使用标准 Windows 窗体 TextBox 的主要问题在于,将其 ReadOnly 属性设置为 true,TextBox 的颜色会更改为 Caption(某种灰色),并且无法设置为任何其他颜色。 通常,我们希望以白色背景显示我们的 SummaryRow。 这就是我包含自己的 TextBox 的原因。 这是一个简单的控件,因为不需要像在通常的 TextBox 中那样进行 EventHandling。 TextBox 具有 IsSummary 属性,用于指示是否应将其用于聚合。 在 OnPaint 事件中直接绘制控件。

   protected override void OnPaint(PaintEventArgs e)
   {         
       Rectangle textBounds;
       textBounds = new Rectangle(this.ClientRectangle.X + 2, this.ClientRectangle.Y + 2,
           this.ClientRectangle.Width - 2, this.ClientRectangle.Height - 2);
       using (Pen pen = new Pen(borderColor))
       {
          e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
          e.Graphics.DrawRectangle(pen, this.ClientRectangle.X, this.ClientRectangle.Y,
              this.ClientRectangle.Width - subWidth, this.ClientRectangle.Height - 1);
          e.Graphics.DrawString(Text, Font, Brushes.Black, textBounds, format);
        }
   }

可以在公共属性 SumaryRowBackColor 中设置 SummaryRow 的颜色。

总结一下!

值的实际求和在方法 calcSummaries() 中完成。 从 DataGridView[RowsAdded] [RowsRemoved][CellValueChanged] 事件的 EventHandlers 调用此方法。 它遍历 DataGridView 的每一行,并汇总在 SummaryColumns 中定义的列的值。

历史

  • 2009 年 5 月 10 日
  • 版本 1.0
© . All rights reserved.