Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access DataGridView rows the order they were added

I have a DataGridView which colors its rows when its States property is set.
States is a String which represents a semicolon-separated numbers list.

If I receive "0;1;2" the three first rows will be colored in purle, green and red respectively.
The problem comes when I sort the datagrid clicking on a column header : colors are applied the same way.

For example :

Names|Labels  
Name1|Label1  
Name2|Label2  
Name3|Label3 

I receive "0;1;2" which means "Purple;Green;Red" :

Names|Labels  
Name1|Label1 => Purple  
Name2|Label2 => Green  
Name3|Label3 => Red 

I sort (descending):

Names|Labels  
Name3|Label3 => Red  
Name2|Label2 => Green  
Name1|Label1 => Purple  

I receive "3;4;5" which means "Yellow;Orange;Pink" :

Names|Labels  
Name3|Label3 => Yellow  
Name2|Label2 => Orange  
Name1|Label1 => Pink 

But this isn't what I was waiting for, I wanted that :

Names|Labels  
Name3|Label3 => Pink  
Name2|Label2 => Orange  
Name1|Label1 => Yellow  

Here is my code :

protected String m_States;

public virtual String States
{
  get { return m_States; }

  set {
    m_States = value;
    if (m_bRunning)
    {
      UpdateColors();
    }
  }
}

private void UpdateColors()
{
  String[] sStates = new String[] { };
  if (m_States != null)
  {
    sStates = m_States.Split(m_sSeparators);

    int nState = 0;
    int nRowNumber = 0;
    foreach (System.Windows.Forms.DataGridViewRow row in Rows)
    {
      nState = int.Parse(sStates[nRowNumber]);

      if (nState < 0 || nState > m_Couleurs_Fond_Etats.Length)
      {
        nState = m_Couleurs_Fond_Etats.Length - 1;
      }
      row.DefaultCellStyle.BackColor = m_Couleurs_Fond_Etats[nState];
      row.DefaultCellStyle.ForeColor = m_Couleurs_Texte_Etats[nState];
      row.DefaultCellStyle.SelectionBackColor = m_Couleurs_Sel_Fond_Etats[nState];
      row.DefaultCellStyle.SelectionForeColor = m_Couleurs_Sel_Texte_Etats[nState];

      nState = 0;
      ++nRowNumber;
    }
  }
}

Isn't there a way to have access to rows the order they were added in the DataGridView?

PS : I first used row.Index instead of nRowNumber, so I believed the problem came from that, but apparently, the Rows collection is reorganized or the foreach parses it according to the rowIndexes.

===== Here is the solution I used thanks to LarsTech's answer =====

After adding my rows, I tagged them this way :

foreach(System.Windows.Forms.DataGridViewRow row in Rows)
{
  row.Tag = row.Index;
}

Then I could use this tag as row number :

private void UpdateColors()
{
  String[] sStates = new String[] { };
  if (m_States != null)
  {
    sStates = m_States.Split(m_sSeparators);

    int nState = 0;
    int nRowNumber = 0;
    foreach (System.Windows.Forms.DataGridViewRow row in Rows)
    {
      nRowNumber = Convert.ToInt32(row.Tag);
      if (nRowNumber >= 0 && nRowNumber < sEtats.Length)
      {
        nState = int.Parse(sStates[nRowNumber]);

        if (nState < 0 || nState > m_Couleurs_Fond_Etats.Length)
        {
          nState = m_Couleurs_Fond_Etats.Length - 1;
        }
        row.DefaultCellStyle.BackColor = m_Couleurs_Fond_Etats[nState];
        row.DefaultCellStyle.ForeColor = m_Couleurs_Texte_Etats[nState];
        row.DefaultCellStyle.SelectionBackColor = m_Couleurs_Sel_Fond_Etats[nState];
        row.DefaultCellStyle.SelectionForeColor = m_Couleurs_Sel_Texte_Etats[nState];

        nState = 0;
      }
    }
  }
}
like image 422
Rifu Avatar asked Jun 22 '12 09:06

Rifu


People also ask

How to get the selected row in DataGridView?

To get the selected rows in a DataGridView controlUse the SelectedRows property. To enable users to select rows, you must set the SelectionMode property to FullRowSelect or RowHeaderSelect.

How to get selected row in GridView vb net?

Selecting Row If you need any particular item in that row you can easily select it using the cells property. In the Gridview, double-Click on the SelectedIndexChanged Event and write the following code: protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)

What is DataGridViewRow?

The DataGridViewRow class represents a row in a DataGridView control. You can retrieve rows through the Rows and SelectedRows collections of the control. Unlike a DataGridViewColumn, a DataGridViewRow physically contains a collection of all of the cells in that row.


1 Answers

You can try using the Tag property of the row to place your row index number. This is how I had my DataGridView initialized:

dataGridView1.Rows.Add(3);
for (int i = 0; i < 3; i++) {
  dataGridView1.Rows[i].Tag = i;
  dataGridView1.Rows[i].Cells[0].Value = "Name " + i.ToString();
  dataGridView1.Rows[i].Cells[1].Value = "Label " + i.ToString();
}

Here is my version of your UpdateColors routine:

private void UpdateColors() {
  String[] sStates = new String[] { };
  if (m_States != null) {
    sStates = m_States.Split(';');
    for (int i = 0; i < sStates.Length;i++) {
      int nState = Convert.ToInt32(sStates[i]);
      foreach (DataGridViewRow row in dataGridView1.Rows) {
        int rowIndex = Convert.ToInt32(row.Tag);
        if (rowIndex == i) {
          row.DefaultCellStyle.BackColor = m_Couleurs_Fond_Etats[nState];
        }
      }
    }
  }
}

I am first looping through your splitted state string to get the row index and to convert the actual value to the color index. Then I loop through the rows to find the matching index property that I placed in the Tag property.

Here is a cleaned up version using just the one loop:

private void UpdateColors() {
  String[] sStates = new String[] { };
  if (m_States != null) {
    sStates = m_States.Split(';');
    foreach (DataGridViewRow row in dataGridView1.Rows) {
      int rowIndex = Convert.ToInt32(row.Tag);
      int colorIndex = Convert.ToInt32(sStates[rowIndex]);
      row.DefaultCellStyle.BackColor = m_Couleurs_Fond_Etats[colorIndex];
    }
  }
}

Needs error checking obviously.

like image 142
LarsTech Avatar answered Oct 13 '22 01:10

LarsTech