Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / Windows Forms
Article

Summary DataGridView

Rate me:
Please Sign up or sign in to vote.
4.63/5 (27 votes)
12 Jan 2010CPOL4 min read 202.1K   34.8K   130   27
DataGridView with an attached SummaryRow
Article_1.gif

Introduction

Developing a Client-Server-Application based on Windows Forms I was searching for a DataGridView component able to display an numeric aggregation of the contents of a column. For example: Summing up the total amount of items in a customer order displayed in one column the Grid. Just like Excel could do. I didn’t found an appropriate solution and so I decided to develop my own component. It should work like the DataGridView with the capability to display a row at the end of the Grid.

For the repositioning and resizing of the SummaryRow I refactored some code which was taken over from the nice Filterable DataGrid from Robert Rhode: gridextensions.aspx. Many thanks to him for his good work.

Getting Started

To use the SummaryDataGridViewTest-Application you have to copy the Nwind.mdb database to the output directory.

Background

A good knowledge of the DataGridView and the Window-Forms library helps in customizing the code but it is not necessary. The use of the SummaryDataGridView is quite simple.

Using the Code

The SummaryDataGridView control can be used like any other control of Windows-Forms and supports design time configuration. It has a set of public properties available in the designer. The use is quite similar to the DataGridView as it is derived from it. To display data, set the DataSource property of the control. Each column that should be summed up must be added to the array of strings SummaryColumns. See Figure 1 and Figure 2 for public properties and how they affect the SummaryDataGridView.

Article_3.gif

Figure SEQ Figure \* ARABIC 1

Article_2.gif

Figure SEQ Figure \* ARABIC 2

The SummaryRow

Using one row of the DataGridView as SummaryRow is very tricky and brings some problems. I didn’t find a solution to lock the SummaryRow at the bottom of the grid which is necessary for scrolling For this reason I decided to use a simple control with Textboxes which is displayed under the DataGridView. All the TextBoxes resize the same way the DataGridView does. Furthermore it’s necessary to draw your own Horizontal scrollbar that will be displayed under our SummaryControlContainer instead of using the h-scrollbar of the DataGridView which would be displayed above our SummaryRow. Accordingly a good part of the code is dealing with positioning, resizing and reordering of our SummaryRow. Summing up the values of one row is the easiest part of the control. The following DataGridView events are handled to synchronize the SummaryRow with DataGridView:

ColumnAdded, ColumnRemoved, ColumnStateChanged, ColumnDisplayIndexChanged

For more information about the synchronization have a look at the methods: reCreateSumBoxes() and resizeSumBoxes() of the SummaryControlContainer class.

Glue between SummaryRow and DataGridView

One question is how you can attach the SummaryRow to the DataGridView. The easiest way would be to use a Control and then include the DataGridView and the SummaryRow in it. The inner grid could be made accessible via a public property. I decided to let the DataGridView create its own SummaryRow. To avoid problems with the designer this is only done runtime. After initialization the DataGridView calls the ChangeParent() method. This method removes the DataGridView from its parent, creates a panel at its place then includes the DataGridView and the SummaryRow in the panel. For the TableLayoutPanel we must determine the exact position of the DataGridView before removing it.

C#
    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();
       }
   }

The ReadOnly TextBox

The main problem in using a standard Windows-Forms TextBox with its ReadOnly property set to true is, that the color of that TextBox changes to Caption (some type of grey) and could not be set to any other color. Usually we want to have our SummaryRow displayed with a white background. That’s the reason why I included my own TextBox. It’s a simple control because no EventHandling is necessary as in a usual TextBox. The TextBox has got an IsSummary property to indicate if it shoud be used for aggregation. Drawing the control is straight forward in the OnPaint event.

C#
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);
     }
}

The color of the SummaryRow could be set in the public property SumaryRowBackColor.

Summing it up!

The actual summation of the values is done in the method calcSummaries(). This method is called from the EventHandlers of the [RowsAdded] [RowsRemoved] and [CellValueChanged] Events of the DataGridView. It iterates through every Row of the DataGridView an summarizes the values of Columns defined in SummaryColumns.

History

  • May, 10th, 2009:
  • Release 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSummary Columns Value Pin
Al Halabi Ahmad24-Nov-23 10:08
Al Halabi Ahmad24-Nov-23 10:08 
Questionerror by compile Pin
v.ryzha17-Jun-15 0:03
v.ryzha17-Jun-15 0:03 
BugLosing sorting feature Pin
Marc Esteve22-Apr-15 20:29
Marc Esteve22-Apr-15 20:29 
GeneralMy vote of 5 Pin
eqbalsajadi18-Apr-14 22:12
eqbalsajadi18-Apr-14 22:12 
QuestionWonderful Article Pin
Serkank949418-Sep-13 7:52
Serkank949418-Sep-13 7:52 
QuestionScrollBars DataGridView Errors Pin
mr.fugio4-Sep-13 16:59
mr.fugio4-Sep-13 16:59 
BugIgnores design time BindingSource column sequence. Pin
Vondersmith18-Apr-13 9:42
Vondersmith18-Apr-13 9:42 
GeneralMy vote of 4 Pin
mahmoud mansourinejad26-Dec-12 17:34
mahmoud mansourinejad26-Dec-12 17:34 
QuestionResize the grid at run time? Pin
Eagle.Chen18-Dec-12 22:27
Eagle.Chen18-Dec-12 22:27 
AnswerRe: Resize the grid at run time? Pin
Eagle.Chen20-Dec-12 23:23
Eagle.Chen20-Dec-12 23:23 
GeneralMy vote of 5 Pin
M3hrdadk11-Nov-12 3:44
M3hrdadk11-Nov-12 3:44 
GeneralMy vote of 5 Pin
musto237-Nov-12 2:54
musto237-Nov-12 2:54 
GeneralMy vote of 5 Pin
leecyi28-Oct-12 20:37
leecyi28-Oct-12 20:37 
AnswerMy vote of 5 Pin
andre4727-Oct-12 16:49
andre4727-Oct-12 16:49 
QuestionAwesome but... Pin
John D. Sanders9-May-12 5:25
John D. Sanders9-May-12 5:25 
AnswerRe: Awesome but... Pin
andre4727-Oct-12 16:58
andre4727-Oct-12 16:58 
GeneralMy vote of 4 Pin
interliuy17-Apr-11 3:46
interliuy17-Apr-11 3:46 
GeneralThanks Pin
YZK29-Mar-11 22:39
YZK29-Mar-11 22:39 
GeneralMy vote of 4 Pin
just_a_predator5-Jan-11 9:27
just_a_predator5-Jan-11 9:27 
Generalsummary fields Pin
basilvde18-Oct-10 7:07
basilvde18-Oct-10 7:07 
GeneralLittle Bug Pin
AntonioNigro6-Sep-10 8:12
AntonioNigro6-Sep-10 8:12 
GeneralRe: Little Bug Pin
LySeZouDn14-Nov-10 15:51
LySeZouDn14-Nov-10 15:51 
GeneralColumns conversion Pin
Marko8516-Aug-10 1:34
Marko8516-Aug-10 1:34 
AnswerRe: Columns conversion Pin
andre4727-Oct-12 23:27
andre4727-Oct-12 23:27 
GeneralSimple keeping of summary line down Pin
galina_eg19-Jan-10 1:24
galina_eg19-Jan-10 1:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.