0

I have a datagridview that is bound to a dataSource and is updated upon loading the form. The datagridview also contains one unbound column caled subTotal which multiples 3 values in a row. Binding of dataSource works fine and the DGV is updated correctly together with the unbound column's values. However, after the Form_Load Event is finished, the program automatically deletes all the rows in my DGV and re-Adds all the items in my DataSource into the DGV on its own. My problem is after re-adding the rows, the subTotal column is only updated for the first 2 rows and the next rows' subTotal column values are set to null. My test case includes a DataTable containing more than 2 rows and no matter how many rows I have, only the first 2 rows' subTotal is being computed.

Could anyone provide me a possible solution and explain why the program automatically removes and re-adds the binded rows to the datagridview and how come only the first 2 rows are being computed? I've been working on this for hours and still couldn't find a solution for my problem.

Thanks!

Here are my codes:

private void ShowSalesOrderWindow_Load(object sender, EventArgs e)
{
    CreateItemsTable();
    itemsDataGridView.AutoGenerateColumns = true;
    itemsDataGridView.DataSource = itemTable;
    CreateSubTotalColumn();
    GenerateItemsDataTable();
}

private void CreateSubTotalColumn()
{
    DataGridViewColumn subTotalCol =
        new DataGridViewTextBoxColumn();
    subTotalCol.Name = "subTotalCol";
    subTotalCol.HeaderText = "Sub-Total";
    subTotalCol.ReadOnly = true;
    itemsDataGridView.Columns.Insert(4, subTotalCol);
}

private void GenerateItemDataTable()
{
    foreach (SalesOrderItem soi in salesOrder.SalesOrderItems)
    {
        DataRow row = itemTable.NewRow();
        row["Product Code"] = soi.Product.ProductCode;
        row["Quantity"] = soi.Quantity;
        row["Price"] = soi.Price;
        row["Discount"] = soi.Discount;
        itemTable.Rows.Add(row);     
    }
}

private void itemsDataGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
    DataGridViewRow row = itemsDataGridView.Rows[e.RowIndex];
    row.Cells["subTotalCol"].Value = ComputeRowSubTotal(row).ToString("c");
}

I also created an empty event handler for the RowsRemoved event just to add a breakpoint and see if it enters it.

1 Answers1

1

RowsAdded may be fired once after x rows were added to DataGridView (as name suggests). In event args passed to method you have property RowCount to see for how many rows this event has been just fired.

Try this code:

private void itemsDataGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
    if (e.RowIndex == -1 || e.RowCount == 0)
    {
        return;
    }

    for (int i = 0; i < e.RowCount; i++)
    {
        var index = e.RowIndex + i;  //get row index

        DataGridViewRow row = itemsDataGridView.Rows[index];
        row.Cells["subTotalCol"].Value = ComputeRowSubTotal(row).ToString("c");
    }
}
gzaxx
  • 17,312
  • 2
  • 36
  • 54
  • For a binded DataTable, every time a row is added into it using itemTable.Rows.Add(row), the RowsAdded event is also being called, doesn't this mean that every time I add a row, it would have to recompute each row's subTotal? Actually I tried something similar to your solution using foreach but thought that there might be a better solution? And the part where rowsRemoved is being executed on its own is still not explained. Thanks for the advice. – BenchPress Man Nov 20 '13 at 08:58
  • No it doesn't mean that as it always give you index of first row added so when it is fired for one row, it will compute subtotal for that row only. To be honest I have no idea why `RowsRemoved` fired, maybe you have `NewRow` that is being removed? Not sure, best why to see what is going on is to check what is passed into event. – gzaxx Nov 20 '13 at 09:02
  • also the line row.Cells["subTotalCol"].Value = ComputeRowSubTotal(row).ToString("c"); should throw an exception since there is no "subTotalCol" column at the time it is first raised (on itemsDataGridView.DataSource = itemTable;). but exceptions in form load events are sometimes swallowed http://stackoverflow.com/questions/1583351/silent-failures-in-c-seemingly-unhandled-exceptions-that-does-not-crash-the-pr – Arie Nov 20 '13 at 09:20
  • @Arie at first I thought that as well but after looking and code I assumed that item table is empty at first and is populated after creating column. This why `RowsAdded` wont be fired before. – gzaxx Nov 20 '13 at 09:23
  • @gzaxx my bad, you're right about the subtotal computation. Been trying to check the rowsRemoved but still haven't got anything from it. Anyways, thanks for your solution, it works! :) Will wait for other answers if there's a clue for my other problem but if not, i'll accept your answer :D – BenchPress Man Nov 20 '13 at 09:35
  • @BenchPress Man still if the property AllowUserToAddRows is set to true (default), the NewRow will be added to DGV and itemsDataGridView_RowsAdded will be raised on data binding (3 times lol), so the exception should be thrown. Also, bound DGVs have this strange habit of doing events connected with data binding 3 times (like selectedindexchange will raise 3 times when datasource is set), also for some reason rows will be added/removed initially 3 times (I replicated the behaviour). – Arie Nov 20 '13 at 09:59