Stephen Tam
Stephen Tam

Reputation: 81

C# - Datagridview compare two cells value and set style

I'm trying to write code in DataGridView event CellFormatting to trigger the logic that compares if column ( qty and scanqty ) values in same row are different, then set background color to Yellow. But occur runtime error

System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.'

Below is my sample code, anyone can help me, thank you very much.

private void dgProductList_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (this.dgProductList.Columns[e.ColumnIndex].Name == "scanqty")
    {
        var sqty = String.IsNullOrEmpty(e.Value.ToString()) ? 0 : int.Parse(e.Value.ToString());
        var qty = int.Parse(dgProductList[e.RowIndex, 1].Value.ToString());

        if (sqty != qty)
        {
            e.CellStyle.BackColor = Color.Yellow;
            e.CellStyle.ForeColor = Color.Red;
        }
        else
        {
            e.CellStyle.BackColor = Color.White;
            e.CellStyle.ForeColor = Color.Black;
        }
    }
}

Upvotes: 0

Views: 752

Answers (3)

Robert S.
Robert S.

Reputation: 2042

As the other answers may be correct, I think the real problem here is that e.RowIndex and e.ColumnIndex can be -1 (e.g. for the header row). So you have to check if these indices are >= 0 first and ignore those with -1.

private void dgProductList_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex >= 0 && this.dgProductList.Columns[e.ColumnIndex].Name == "scanqty")
    {
        // ...
    }
}

Upvotes: 1

Caius Jard
Caius Jard

Reputation: 74690

Consider something like this, for performance reasons:

private void dgProductList_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == COL_INDEX_OF_SCANQTY_COLUMN)
    {
        var sqty = (DATATYPE_OF_SCANQTY)e.Value;
        var qty = (DATATYPE_OF_QTY)dgProductList[1, e.RowIndex].Value;

        if (sqty != qty)
        {
            e.CellStyle.BackColor = Color.Yellow;
            e.CellStyle.ForeColor = Color.Red;
        }
        else
        {
            e.CellStyle.BackColor = Color.White;
            e.CellStyle.ForeColor = Color.Black;
        }
    }
}

You don't need to round trip from string and back to int etc. Also you are happy to hard code that QTY is always column 1 but you look up the name of the column for scanqty and compare it to string to check if it's the scanqty column - you might as well hard code that too

If you don't know the datatypes of the values, pause it in the debugger and take a look..

Upvotes: 1

Mong Zhu
Mong Zhu

Reputation: 23732

when using the [ ] operator to access data in the DataGridView the syntax is :

dgProductList[columnIndex, rowIndex]

enter image description here your are doing it the reverse way. please change this line:

var qty = int.Parse(dgProductList[e.RowIndex, 1].Value.ToString());

to this:

var qty = int.Parse(dgProductList[1, e.RowIndex].Value.ToString());

another possibility could be to use the column name qty

var qty = int.Parse(dgProductList["qty", e.RowIndex].Value.ToString());

Upvotes: 1

Related Questions