C# – Adding rows to datagridview with existing columns

c++datagridviewwinforms

I have a DataGridView with several created columns. I've add some rows and they get displayed correctly; however, when I click on a cell, the content disappears.

What am I doing wrong?

The code is as follows:

foreach (SaleItem item in this.Invoice.SaleItems)
{
    DataGridViewRow row = new DataGridViewRow();
    gridViewParts.Rows.Add(row);

    DataGridViewCell cellQuantity = new DataGridViewTextBoxCell();
    cellQuantity.Value = item.Quantity;
    row.Cells["colQuantity"] = cellQuantity;

    DataGridViewCell cellDescription = new DataGridViewTextBoxCell();
    cellDescription.Value = item.Part.Description;
    row.Cells["colDescription"] = cellDescription;

    DataGridViewCell cellCost = new DataGridViewTextBoxCell();
    cellCost.Value = item.Price;
    row.Cells["colUnitCost1"] = cellCost;

    DataGridViewCell cellTotal = new DataGridViewTextBoxCell();
    cellTotal.Value = item.Quantity * item.Price;
    row.Cells["colTotal"] = cellTotal;

    DataGridViewCell cellPartNumber = new DataGridViewTextBoxCell();
    cellPartNumber.Value = item.Part.Number;
    row.Cells["colPartNumber"] = cellPartNumber;
}

Thanks!

Best Solution

Just to extend this question, there's also another way to add a row to a DataGridView, especially if the columns are always the same:

object[] buffer = new object[5];
List<DataGridViewRow> rows = new List<DataGridViewRow>();
foreach (SaleItem item in this.Invoice.SaleItems)
{
    buffer[0] = item.Quantity;
    buffer[1] = item.Part.Description;
    buffer[2] = item.Price;
    buffer[3] = item.Quantity * item.Price;
    buffer[4] = item.Part.Number;

    rows.Add(new DataGridViewRow());
    rows[rows.Count - 1].CreateCells(gridViewParts, buffer);
}
gridViewParts.Rows.AddRange(rows.ToArray());

Or if you like ParamArrays:

List<DataGridViewRow> rows = new List<DataGridViewRow>();
foreach (SaleItem item in this.Invoice.SaleItems)
{
    rows.Add(new DataGridViewRow());
    rows[rows.Count - 1].CreateCells(gridViewParts,
        item.Quantity,
        item.Part.Description,
        item.Price,
        item.Quantity * item.Price,
        item.Part.Number
    );
}
gridViewParts.Rows.AddRange(rows.ToArray());

The values in the buffer need to be in the same order as the columns (including hidden ones) obviously.

This is the fastest way I found to get data into a DataGridView without binding the grid against a DataSource. Binding the grid will actually speed it up by a significant amount of time, and if you have more then 500 rows in a grid, I strongly recommend to bind it instead of filling it by hand.

Binding does also come with the bonus that you can keep the Object in tact, f.e. if you want to operate on the selected row, you can do this is the DatagridView is bound:

if(gridViewParts.CurrentRow != null)
{
    SaleItem item = (SalteItem)(gridViewParts.CurrentRow.DataBoundItem);
    // You can use item here without problems.
}

It is advised that your classes which get bound do implement the System.ComponentModel.INotifyPropertyChanged interface, which allows it to tell the grid about changes.

Related Question