0

I have this problem: in a windows forms C# app I have a normal form with a DataGridView with CellFormatting event (I need to format 5-6 columns; with 1 everything is ok).

The problem is that the form is not completely loaded/rendered (some elements don't get the right color, the labels are incomplete). The dataGridView (with 2 rows) also has some problems (when I click on a row that has a cell formatted with a backcolor, this color goes on the other row).

I have enabled the DoubleBuffering (the solution with the new class DBDataGridView available here: How to prevent DataGridView from flickering when scrolling horizontally?) but it still does not work.

I have noticed that among the properties of the dataGridView are these 2: -DoubleBuffered: true -DoubleBufferedEnabled: false

Could be this the problem ? How can I set to true the DoubleBufferedEnabled ?

I am using Visual Studio 2013, version 12.0.3 update 4

These are the dataGridView properties:

These are the dataGridView properties

Thanks

UPDATE here because in the comments it is not possible to attach images:

yes, my app is winforms. this is the code that works (the "cell" is defined outside as "private DataGridViewCell cell = null;"). Some columns are hidden (like "accettato") and I use them to format other columns.

private void dataGridPrevW_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
     {
         
         if ((e.ColumnIndex == dataGridPrevW.Columns["costo"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["acconti"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["complDaIncassare"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["costoLavEseg"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldoFinePr"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldolaveseg"].Index
             ) && e.Value != null)
         {
             e.CellStyle.Format = "N02";
         }

         if ((e.ColumnIndex == dataGridPrevW.Columns["costo"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["acconti"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["complDaIncassare"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["costoLavEseg"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldoFinePr"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldolaveseg"].Index
             ) && (e.Value == null || e.Value.ToString().Trim().Equals("")))
         {
             e.CellStyle.Format = "";
         }

         cell = dataGridPrevW.Rows[e.RowIndex].Cells[e.ColumnIndex];

         
         if (e.ColumnIndex == dataGridPrevW.Columns["acconti"].Index)
         {
             cell.ToolTipText = dataGridPrevW.Rows[e.RowIndex].Cells["stringaAcconti"].Value.ToString();
         }

         
      /*if (e.ColumnIndex == dataGridPrevW.Columns["descrizione"].Index)
         {
             if (dataGridPrevW.Rows[e.RowIndex].Cells["accettato"].Value != null && dataGridPrevW.Rows[e.RowIndex].Cells["accettato"].Value.ToString().Equals("1"))
             {
                 cell.Style.BackColor = Color.PaleGreen;
                 cell.ToolTipText = "Accettato";
             }

             if (dataGridPrevW.Rows[e.RowIndex].Cells["chiuso"].Value != null && dataGridPrevW.Rows[e.RowIndex].Cells["chiuso"].Value.ToString().Equals("1"))
             {
                 cell.Style.BackColor = Color.Moccasin;
                 cell.ToolTipText = "Chiuso";
             }

               if (dataGridPrevW.Rows[e.RowIndex].Cells["chiusobn"].Value != null && dataGridPrevW.Rows[e.RowIndex].Cells["chiusobn"].Value.ToString().Equals("1"))
               {
                   cell.Style.BackColor = Color.Gainsboro;
                
               }

               if (dataGridPrevW.Rows[e.RowIndex].Cells["chiusonb"].Value != null && dataGridPrevW.Rows[e.RowIndex].Cells["chiusonb"].Value.ToString().Equals("1"))
               {
                   cell.Style.BackColor = Color.DarkGray;

               }
         } */
     } 

and this is the result (OK with the commented code):

enter image description here

and this is the result (KO) without the comments, I mean the whole uncommented code:

enter image description here

As you can see, in the top the elements are not completely loaded (there are the green parts and the "plus" button appears 2 times, the title is different - "Elenco cartelle per paziente" instead of "Cartella paziente" that is the title of the previous form). The three rows are ok, formatted by the uncommented lines (I think there is a problem here, too, because if I click the green row, the green color disappears and it appears again if I click on another row).

UPDATE: it seems the problem is on the form itself because the top elements are not in the dataGridView...I also tried to set DoubleBuffered = true on the form but I got the same behavior. Or maybe because the DataGridView is not doubble buffered then the form is not completely loaded ??

UPDATE: the problem with the green color that dissapears when click on that row is "normal"...it means that the setting AlternatingRowColor overrides the color that the cell already has (set before in CellFormating or elsewhere). I have solved it this way:

 private void dataGridPrevW_SelectionChanged(object sender, EventArgs e)
    {
        for (int counter = 0; counter < (dataGridPrevW.Rows.Count); counter++)
        {
            if (dataGridPrevW.Rows[counter].Cells["descrizione"].Style.BackColor == Color.PaleGreen)
            {
                dataGridPrevW.Rows[counter].Cells["descrizione"].Style.SelectionBackColor = Color.PaleGreen;
            }
        }
    }

Here is the code for DataBindingComplete:

private void dataGridPrevW_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
   {
       for (int counter = 0; counter < (dataGridPrevW.Rows.Count); counter++)
       {
           if (dataGridPrevW.Rows[counter].Cells["accettato"].Value != null && dataGridPrevW.Rows[counter].Cells["accettato"].Value.ToString().Equals("1"))
           {
               dataGridPrevW.Rows[counter].Cells["descrizione"].Style.BackColor = Color.PaleGreen;
               dataGridPrevW.Rows[counter].Cells["descrizione"].ToolTipText = "Accettato";
           }

           if (dataGridPrevW.Rows[counter].Cells["stringaAcconti"].Value != null)
           {
               dataGridPrevW.Rows[counter].Cells["acconti"].ToolTipText = dataGridPrevW.Rows[counter].Cells["stringaAcconti"].Value.ToString();
           }
    ...
    }

and here is the code for CellFormatting:

private void dataGridPrevW_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
     {
         
         if ((e.ColumnIndex == dataGridPrevW.Columns["costo"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["acconti"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["complDaIncassare"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["costoLavEseg"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldoFinePr"].Index ||
             e.ColumnIndex == dataGridPrevW.Columns["saldolaveseg"].Index
             ) && e.Value != null)
         {
             e.CellStyle.Format = "N02";
         }
      ...
      }

Thanks again

Adrian T
  • 93
  • 1
  • 11
  • Assuming you are using a winforms `DataGridView` and I could be mistaken, however, 5-6 columns of data is not a lot of data and I would think double buffering would not necessarily be needed. What is the code doing in the grids `CellFormatting` event? Are you sure it may not be calling the `CellFormatting` code unnecessarily? – JohnG Jun 05 '22 at 00:52
  • It appears you have multiple issues. The grid and the form(s). I will focus on the grid and its `CellFormatting` code. You should note that the grids `CellFormatting` event fires many-many times. Like when the user simply moves the cursor over a cell or when the grid is scrolled. And in BOTH those cases, your code is getting called unnecessarily. Example… if you look at the first two `if` statements in the code… Both `if` statements check to see if the cell being formatted is from one of six columns, then it checks the cells value if it is one of the target columns cells. – JohnG Jun 05 '22 at 21:46
  • In the first `if` statement, the last item checked is to see if the cells value, is NOT `null`, and if it has a value, then format the cell with… `e.CellStyle.Format = "N02";`. The second `if` statement checks all the same columns AGAIN and if the cells value IS `null`, then set the cells format to nothing with… `e.CellStyle.Format = "";` … ? … this code and the rest of the code below the `if` statements is called many times over unnecessarily. – JohnG Jun 05 '22 at 21:46
  • The point I am trying to make is that formatting the cells as the code does when the user moves the cursor over the cell or scrolls the grid… then clearly there is NO reason to call your code since the CELL VALUES HAVE NOT CHANGED. In other words, I would move that code to the grids `CellValueChanged` event which will only fire when a cells value actually changes. It is unnecessary to re-color the cells or set a cells tool tip… if the cells value does not change. – JohnG Jun 05 '22 at 21:47
  • You may want to put a `Debug.WriteLine` statement inside the event and check how many times the code is called unnecessarily. Example: create a global `int` variable called `cfCount` and set it to zero (0). Then in the grids cell formatting event add the code … `Debug.WriteLine(“CellFormatting called: “ + ++cfCount);` as the first line of code in the event. Then run the code and move the mouse over the grid or scroll the grid and you will see that the code is called many-many times unnecessarily. – JohnG Jun 05 '22 at 21:48
  • Of course, it not necessary to call CellFormatting for every event...it is enough just for the real cell change. But in all my searches "how to format cell datagridview C#" I got "cellFormatting" as result. I will try CellValueChanged ...this should solve the problem ....I will let you know. Thankx – Adrian T Jun 07 '22 at 15:03
  • Hi, it.doesn't work with CellValueChanged. It passes in this event only one time, with rowIndex=-1 and column indexp that goea from -1 to the last column index (13 o 14). – Adrian T Jun 09 '22 at 07:17
  • _"It passes in this event only one time, with rowIndex=-1 and column indexp that goea from -1 to the last column index (13 o 14)."_ ... ? ... what do you mean by only one time? Is `e.RowIndex` always -1? Column index that goes from -1 to last column? It would help if you showed the code in the grid's `CellValueChanged` event. – JohnG Jun 09 '22 at 07:26
  • I mean in debug it passes only 1 time from -1 to 13 instead of a loop for every row (and column). I am not sure if this is the right event because the cells actually don't change. Maybe there's an event like "onLoad" or similar. I will show you the code later....but it is almost the same as the actual code in CellFormatting – Adrian T Jun 09 '22 at 10:00
  • the e.RowIndex is always -1 ....this is why I said "it passes only one time"...there is no loop for rows but just only one iteration for the rowIndex = -1 and columnIndex = from -1 to 13. I don't understand why it starts with -1 for both rows and columns. In the worst case, it should start with 0. – Adrian T Jun 09 '22 at 15:34
  • Sorry, I mean "it enters in that method"...here is the code: ** private void dataGridPrevW_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex > 0 && e.ColumnIndex > 0) { cell = dataGridPrevW.Rows[e.RowIndex].Cells[e.ColumnIndex]; if ((e.ColumnIndex == dataGridPrevW.Columns["costo"].Index ||....** . The whole code does not fit here. However, it is the same like in the CellFormatting except for the assigning of the Format...now it should be used "cell.Style.Format". – Adrian T Jun 09 '22 at 21:02
  • _"The whole code does not fit here."_ ... then [edit] your question and add it to the bottom of your question. It should be there anyway and should not be in a comment. – JohnG Jun 09 '22 at 21:45
  • it seems working good with this: private void dataGridPrevW_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { for (int counter = 0; counter < (dataGridPrevW.Rows.Count); counter++) { dataGridPrevW.Columns["descrizione"].Index) if (dataGridPrevW.Rows[counter].Cells["accettato"].Value != null && dataGridPrevW.Rows[counter].Cells["accettato"].Value.ToString().Equals("1")) { dataGridPrevW.Rows[counter].Cells["descrizione"].Style.BackColor= Color.PaleGreen; – Adrian T Jun 09 '22 at 21:51
  • Please [edit] your question and add the code to the bottom your question. Some people may not read the comments and code in comments is difficult to read. Again, PLEASE [edit] your question and add the code to the bottom. – JohnG Jun 09 '22 at 22:00
  • Layout and DataBindingComplete events also work but they are called many times...Layout seems called every time the layout of the datagridview changes...when the form is open, when the data are loading, etc...about 4 times in my case (there are also 4 rows) . DataBindingComplete is called about 19 times. However, there is no problem like fliker or delays. I can't find an event that is called only 1 time after (or during) the data loading. – Adrian T Jun 09 '22 at 23:10
  • Hmm… OK It appears you have this figured out. Good Luck. – JohnG Jun 09 '22 at 23:13

0 Answers0