none
Iterating a DataGridView and underlying DataTable at once to colorize rows

    Question

  • I have a DataGridView attached to an underlying DataTable.  After I load the data table, I apply a BindingSource.Filter to the data in order to hide some of the data that I don't need (based on user input).  I then bind it to the DataGridView.

    After I've done that, I need to go through the rows and colorize some rows based on one of the columns' data.  I tried this

     

    for (int i=0; i<logEntries.Tables["Logs"].Rows.Count; i++)
    {
            DataRow r = logEntries.Tables["Logs"].Rows[i];
            statusCode = (HttpStatusCode)r["HTTPStatus"];
            if (statusCode == 1234)
            {
                   dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red;
            }
    }

    This method doesn't work as it causes an exception: 

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

    My theory is that there is a mismatch between the number of Rows in the DataGrid and the number of Rows in the underlying data set due to the BindingSource.Filter I applied before calling this.

    If I changed my loop condition to walk the DataGridView Rows rather than the underlying data table, then I run into a mismatch issue as well.  DatatGridView.Rows[0] may not map to the first element in the DataTable due to my filtering.

    So basically I'm not sure how to iterate over the data in this case and then how to make a mapping between the DataGridView Row number and the underlying data table number.  

    I've been able to use something similar in the past, where I walked the entire DataTable and changed a value in the data Table itself, then my "i" value in that case indexes only into the DataTable.  This question adds a new complexity.

     

    I may be off on the wrong track completely here.  

    Could I instead have a method that changes row color based on a field changing in the underlying data table via a callback?

    Wednesday, April 07, 2010 4:14 PM

Answers

  • Well I solved it, and I was being overly complicated, here is the fix:

     

            private void MarkHttpStatus()
            {
                foreach (DataGridViewRow dataGridViewRow in dataGridView1.Rows)
                {
                    int httpStatus = (int)dataGridViewRow.Cells["HTTPStatus"].Value;
    
                    //unauthorized
                    if (httpStatus == (int)HttpStatusCode.Unauthorized)
                    {
                        dataGridViewRow.Cells["IP"].ToolTipText = "HTTP Status = " + status.ToString() + " (" + status + ")";
                        dataGridViewRow.DefaultCellStyle.BackColor = Color.Red;
                    }
                    else
                    {
                        dataGridViewRow.DefaultCellStyle.BackColor = Color.White;
                    }
                }
            }

    • Marked as answer by Matt Fischer Wednesday, April 07, 2010 8:20 PM
    Wednesday, April 07, 2010 8:20 PM