none
Change Row Colour in Datagridview based on value of a cell in that row.

    Question

  • I have a simple database that displays information in various datagridview controls on the same form. One thing I would like to do is change the colour of a row if the value from a cell returns "poor", or "fair"

    I call a private function to go through each row in the datagrid just after it is connected to the bingingSource. I can get it to change the colour, but it formats all the rows with that colour, and I want only the row that returned the value to be changed.

    c# Syntax (Toggle Plain Text)
    1. private void checkForSurveyColour()
    2. {
    3. foreach (DataGridViewRow row in dataGridView1.Rows)
    4. {
    5. try
    6. {
    7. CNumColour = dataGridView1.CurrentRow.Cells["RepVisits"].FormattedValue.ToString();
    8. if (CNumColour != null)
    9. {
    10. foreach(DataGridViewCell cells in row.Cells)
    11. {
    12. if (CNumColour == "Fair")
    13. {
    14. cells.Style.ForeColor = Color.Pink;
    15. }
    16. else if (CNumColour == "Poor")
    17. {
    18. cells.Style.ForeColor = Color.Red;
    19. }
    20. }
    21. }
    22.  
    23.  
    24. }
    25. catch(System.Exception ex)
    26. {
    27.  
    28. }
    29. }
    30.  
    31.  
    32. }

    Thanks.

     

    Wednesday, September 05, 2007 11:48 PM

Answers

  • I have changed a few things from the code you provided.

     

    I have removed e.RowIndex > 0

     

    Also I changed the location of the RepVisits declaration.

     

    The last thing I did, and this was to fix the problem with formatting the row if there were more than could fit on the dgv.  I changed the dgv AutoSizeColumnsMode from "DisplayedCells" to "AllCells".

     

    Now the colour change works as it should.

     

    thanks for your help in getting me started on the correct track.

     

    Regards.

     

     

     

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

    {

    try

    {

    if (e.ColumnIndex == this.dataGridView1.Columns["RepVisits"].Index)

    {

    string RepVisits = e.Value.ToString();

    if (RepVisits != null)

    {

    if (RepVisits == "Poor" || RepVisits == "Fair")

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red;

    }

    else

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Black;

    }

    }

    }

    }

    catch

    {

    }

     

    }

     

    Wednesday, September 12, 2007 7:12 PM

All replies

  • You can handle the CellFormating event as something like this:

    void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

            {

                if (e.RowIndex > 0 &&

                    e.ColumnIndex == this.dataGridView1.Columns["RepVisits"].Index)

                {

                    if(e.Value != null)
                    {

                         string CNumColour =  e.Value.ToString();

     

                         if (CNumColour == "Pool" || CNumColour == "Fair")

                         {

                              this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red;

                         }
                    }

                }

            }

    Friday, September 07, 2007 10:33 AM
  • Thanks for the reply.

     

    When I implement the solution you provided I get a null exception because an empty grid is loaded when the program starts and there is no "RepVisits" value.

     

    adding a try...catch to check for null returned an error that said something like "unable to evaluate ...due to overloaded state, check for infinite loop problem?"

     

    I am really close with my code, it colours the correct rows, but Only if it is the only row in the grid. 

     

    Here's some more back ground.....

    I have a sqlexpress database with a customer table.

    My app loads 3 datagridviews one of which displays the customers table.(datagridview1)

    When the app loads the dgv's are blank.  There are 4 ways to populate dgv1  (Cust#, Prov, City, Company)

     

    When you query by Cust#, my code works great... "RepVisits" == Poor it colours the font pink.  When "RepVisits" == Fair it colours the font red.

     

    When sorting by Company(There are several locations for many of the companies)  The dgv1 query will return many results with the same name (They differ by address, cust# etc) and when it does it colours the whole dgv1 to match the one result with "Fair, Poor".

     

    When sorting by city or Prov it will not change any of the results eventhough the "RepVisit" trigger is present.

     

    I was trying to avoid the formatting event for dgv cells as it seems to me the larger the results the slower the performance if it has to go through each cell.

     

    Thanks again for your help

     

     

    Friday, September 07, 2007 3:41 PM
  • I sorry for the mistake in my above post, I’ve edit it to update. I'm afraid you cannot avoid the CellFormating or CellPainting event, since if you do the coloring stuff right after populating the DataGridView, the color would disappear when sorting. I test  CellFormating with 50000 lines of records to find the performance is kind of acceptable.

    Code Snippet

    private void Form4_Load(object sender, EventArgs e)

    {

        DataTable dt = new DataTable();

        dt.Columns.Add("id",typeof(int));

        dt.Columns.Add("RepVisits");

        for (int j = 0; j < 50000;)

        {

              dt.Rows.Add(j++, "Fair");

              dt.Rows.Add(j++, "Poor");

              dt.Rows.Add(j++, "Other");

        }

        this.dataGridView1.DataSource = dt;

            this.dataGridView1.CellFormatting +=
    new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);

    }

     

    void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

    {

         if (e.RowIndex > -1 && e.ColumnIndex == this.dataGridView1.Columns["RepVisits"].Index)

         {

             if (e.Value != null)

             {

               string RepVisits = e.Value.ToString();

               if (RepVisits == "Fair")

               {

                 this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Pink;

               }

               if (RepVisits == "Poor")

               {

                   this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red;

               }

            }

        }

    }

     

     

     

    Friday, September 07, 2007 6:02 PM
  • Well it's getting closer.  Now if the first row is the one with "fair" or "poor" in the RepVisits column it is Not formatted correctly.

    Also, sometimes it will not format the row correctly until the datagrid view is sorted or moved via scroll bars.

     

    Here is the code i have used. 

    [code=c#]

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

    {

    if (e.RowIndex > 0 && e.ColumnIndex == this.dataGridView1.Columns["RepVisits"].Index)

    {

    if (e.Value != null)

    {

    string RepVisits = e.Value.ToString();

    if (RepVisits == "Fair")

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Pink;

    }

    if (RepVisits == "Poor")

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red;

    }

    }

    }

     

    }

    [/code]

    While debugging i watched the RepVisits String which never appears to change from null....?

     

    thanks again.

     

    Saturday, September 08, 2007 7:09 PM
  •  binteron wrote:

    Well it's getting closer.  Now if the first row is the one with "fair" or "poor" in the RepVisits column it is Not formatted correctly.



    For this, change e.RowIndex > 0 to e.RowIndex > -1

     binteron wrote:

    Also, sometimes it will not format the row correctly until the datagrid view is sorted or moved via scroll bars.



    Could you show me a case when it don't format correctly?

    Sunday, September 09, 2007 3:05 AM
  • I have changed a few things from the code you provided.

     

    I have removed e.RowIndex > 0

     

    Also I changed the location of the RepVisits declaration.

     

    The last thing I did, and this was to fix the problem with formatting the row if there were more than could fit on the dgv.  I changed the dgv AutoSizeColumnsMode from "DisplayedCells" to "AllCells".

     

    Now the colour change works as it should.

     

    thanks for your help in getting me started on the correct track.

     

    Regards.

     

     

     

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

    {

    try

    {

    if (e.ColumnIndex == this.dataGridView1.Columns["RepVisits"].Index)

    {

    string RepVisits = e.Value.ToString();

    if (RepVisits != null)

    {

    if (RepVisits == "Poor" || RepVisits == "Fair")

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red;

    }

    else

    {

    this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Black;

    }

    }

    }

    }

    catch

    {

    }

     

    }

     

    Wednesday, September 12, 2007 7:12 PM
  • Hi have a look of this link also

    http://www.dotnetpools.com/Article/ArticleDetiail/?articleId=74
    Saturday, November 10, 2012 6:27 PM