Total a column in a .NET WinForms DataGrid

One way is to loop through rows in the grid and sum the values for the column of interest. This is what the code below does. It then displays the total in a label control. The code assumes column 1 in our datagrid contains a decimal value to be totalled.

There are a few tricks to watch for. If the grid is not read only the user can edit a cell in the column you are summing and change its value. You need to react to the underlying textbox's TextChanged event and keep your total accurate as the user is editing the data. To do this I use a GridTableStyle to format the DataGrid and hook into the TextChanged event for the DataGridTextBoxColumn associated with the column. When this event fires the AmountChanged handler is invoked to total the values.

When the grid is initially populated and when deleting and inserting rows the total also needs to be adjusted. In these cases you must also call the AmountChanged routine.

The AmountChanged method loops through the grid, pulls the values from it, and sums them. If the cell is being edited the value will not yet be available in the DataGrid so you it is retrieved from the DataGridTextBoxColumn tied to the cell. On deletes and inserts special processing is also required. You can inform AmountChanged how it was called by passing in different values for its sender parameter.

Lastly, before summing the value we must test that it is numeric. The IsDecimal function accomplishes this.

    . . . 
    // Code to format the grid.

    // Create a GridTableStyle.
    DataGridTableStyle aGridTableStyle = new DataGridTableStyle(); 
    aGridTableStyle.MappingName = "MyTable";

    // Create a TextBox GridColumnStyle.
    DataGridTextBoxColumn aCol1 = new DataGridTextBoxColumn();
    aCol1.MappingName = "MyAmount";
    aCol1.Alignment = HorizontalAlignment.Left;
    aCol1.TextBox.Enabled = true;
    aGridTableStyle.GridColumnStyles.Add(aCol1);

    // Add the GridColumnStyle to the Table Style.
    dataGrid.TableStyles.Add(aGridTableStyle);

    // Hook into the TextChanged event. 
    DataGridTextBoxColumn tbc = (DataGridTextBoxColumn)aGridTableStyle.GridColumnStyles[1]; 
    tbc.TextBox.TextChanged += new EventHandler(AmountChanged); 
    . . .

    private void AmountChanged (object sender, EventArgs e)
    {
        // Get the number of rows in the grid.
        int numRows = dataGrid.BindingContext[dataGrid.DataSource, dataGrid.DataMember].Count; 
        double dblAmt = 0;
        string strAmt = "";

        // Sum the amount on each row.
        for (int i = 0; i < numRows; i++)
        {
            // Use the amount from the datagrid.
            strAmt = dataGrid[i, 1].ToString();
            //
            // If called from the TextChanged event of a TextBox in the 
            // DataGrid corresponding to a cell that is currently being 
            //edited the value will not be available in the grid yet. 
            // Get it from the textbox.
            //
            if ((sender.ToString().ToUpper().IndexOf("TEXTBOX") > 0) &&
                (i == dataGrid.CurrentRowIndex))
            {
                // If the cell is being edited the value will not be
                // available in the grid yet. Get it from the textbox.
                DataGridColumnStyle dgc = 
                dataGrid.TableStyles[0].GridColumnStyles[1];
                DataGridTextBoxColumn aTxt = (DataGridTextBoxColumn) dgc;
                strAmt = aTxt.TextBox.Text;
            }

            // If the value is not numeric don't add it.
            if (IsDecimal(strAmt) == false)
                strAmt = "0";

            dblAmt += Convert.ToDouble(strAmt);
        }
        lblTotal.Text = dblAmt.ToString();
    }

After the grid is initially populated and when a rows is deleted you can call the AmountChanged methods like this:

    AmountChanged("GridLoaded", e);
    . . . 
    AmountChanged("DeleteDataRow", e);

Here is the routine to test for decimal values.

    public static bool IsDecimal(string theValue
    {
        try
        {
            Convert.ToDouble(theValue);
            return true;
        } 
        catch 
        {
            return false;
        }
    } //IsDecimal



About TheScarms
About TheScarms


Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page


© Copyright 2024 TheScarms
Goto top of page