简体   繁体   中英

How can i change datagridview specific checkbox cell color and check based on database value?

I have a datagridview with a checkbox column. The checkbox cell should change the color and check status based on a specific value in the database table column. If that value is "grafcheck", then the checkbox cell and checkbox should be green and checked. If the field in the table is null, the checkbox cell should be white and unchecked. The below code does what it should but it marks as checked every checkbox and makes them all green regardless if the value is present or not.

using (SqlConnection con = new SqlConnection(@"Data Source=GAMEWORK\SQLEXPRESS;Initial Catalog=Tida;Integrated Security=True"));
            {

                DataGridViewCellStyle style = new DataGridViewCellStyle();
                style.BackColor = Color.Green;
                style.ForeColor = Color.White;

                string sql = "SELECT GraficaFinal FROM Comenzi WHERE GraficaFinal='grafcheck'";
                con.Open();
                SqlCommand cmd = new SqlCommand(sql, con);
                SqlDataReader reader = cmd.ExecuteReader();
                
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        string graph = reader["GraficaFinal"].ToString();

                        for (int i = 0; i < ComNef.Rows.Count; i++)
                        {
                                if (graph == "grafcheck")
                                {
                                    ComNef.Rows[i].Cells["chkbxGrafica"].Value = true;
                                    ComNef.Rows[i].Cells["chkbxGrafica"].Style = style;
                                }

                                else if (graph == "")
                                {
                                    ComNef.Rows[i].Cells["chkbxGrafica"].Value = false;
                                    ComNef.Rows[i].Cells["chkbxGrafica"].Style.BackColor = Color.White;
                                }

                        }
                        
                    }

                }
                con.Close();
            }

You may want to re-think your approach here. First you say that after the code runs, all the check boxes are checked and green. And from what I can see this makes sense because the query is only getting the rows… … WHERE GraficaFinal='grafcheck' … So if you are getting data back from the query… then ALL the rows will have grafcheck . This pretty much makes the… if (graph == "grafcheck") {.. … statement superfluous.

Another issue…, the… while (reader.Read()) { … … loop is iterating over the lines read, so the code reads a line, then sets the graph variable like…

string graph = reader["GraficaFinal"].ToString();

this is fine… HOWEVER … the code then (for some unknown reason) “loops” through ALL the rows in the grid …? … this can not be right. Basically, is what will happen when using the for loop through the rows of the grid will set each rows check box state to the “current” lines graph value… regardless of what the actual value is in the GraficaFinal cell on that row. However we already know it will be “grafcheck.”

If you trace this code it will basically set all the check box values and color to whatever the LAST row in the data contains. In other words… I am confident you do NOT want a for loop there, you would ONLY be setting ONE (1) value in that row. And this brings up “why” is the code “manually” adding the values to the grid? I am confident you could use a DataTable and get it filled directly from the query. Then you could simply use the DataTable as a DataSource to the grid. The code to fill the table may look something like…

DataTable GridDT = new DataTable(“Comenzi”);
GridDT.Load(reader);

This would fill the table with one column of GraficalFinal data based upon the query you have.

Also… It is unclear “where” the chkbxGrafica column in the ComNef grid is coming from… I will assume you are adding the column in the designer or possibly in some code that is not shown. If you are adding the column manually to the GRID as it appears you are, then there is an easier approach.

Instead of manually adding the column to the GRID, I suggest you manually add the column to the DataTable we previously got from the DB query. This may appear trivial as to whether you add the column to the GRID or TABLE… however, the GRID column does not have the ability to use an “Expression” in its column. The DataTable allows for a column to contain an “expression”…

DataColumn.Expression Property

This will come in very handy where we want to set the chkbxGrafica cell to a checked or not checked state. This expression may look something like…

"IIF(GraficalFinal = 'grafcheck', 'true', 'false')"

This will “automatically” set the check box cell to the proper check state. NOTE… because the check box column is an “expression” column… then the user will NOT be able to change the check box state directly, however… changing the GraficaFinal cell WILL change the check box state. This simple one line of code for the “expression” column would eliminate all the code that loops through the grid and sets the check box values.

In addition… once the code is running and the user “changes” a GraficalFinal cell value to any value other than grafcheck … then… the check box on that row will automatically become “unchecked.” Obviously, if the cells value IS “grafcheck” then this will set the check box to “checked”

Unfortunately, this is NOT going to “color” the cell as you want. For this, we WILL need to look to the GRID. Ňɏssa Pøngjǣrdenlarp commented a link that is one of many possible ways to color the grid cells. The most common and intuitive grid event to change the cells color would be the grids CellFormatting event. This event will fire when the cell needs to be formatted and in this event we could simply check to see what the check box value is and then color it appropriately.

A word of caution… using the grids CellFormatting event for this works well, however, if you drop a Debug statement into the event… you will note that the event will fire many more times than is needed. Example, it may fire when the user simply moves the cursor over the cells in the grid. This is one reason I may choose a different event like the grids CellValueChanged event.

Unfortunately, this opens the door to more work since that event will NOT fire when grids DataSource is set. The CellFormatting event WILL fire when the grids DataSource is set. So… if we used the grids CellValueChanged event instead of the grids CellFormatting event… then… we kind of end up in the same boat we are already in… we will need to implement addition code to “loop” through all the rows in the GRID and set the cell colors right after the grids DataSource is set. Granted, this eliminates the cell getting formatted when it doesn't need it, however, it creates more work for you. In the example below… I will use the grids CellFormatting event.

So… to sum up… add a Boolean type column with an “expression” to the DataTable . This will set the check box values based upon what the GraficalFinal cell contains. Then wire-up the grids CellFormatting event to set the cells color.

A small yet complete example of what is described above is demonstrated in the code below. NOTE… obviously the GetDataFromDB method simply creates a single column table with some random values and you would change this code to get the GraficaFinal table from your DB. If you drop a DataGridView onto a form and wire up its CellFormatting event, then, below is what the code should produce. Good Luck.

在此处输入图像描述

DataTable GridDT;
DataGridViewCellStyle CheckedStyle;
DataGridViewCellStyle UnCheckedStyle;

public Form1() {
  InitializeComponent();
  CheckedStyle = new DataGridViewCellStyle();
  UnCheckedStyle = new DataGridViewCellStyle();
  CheckedStyle.BackColor = Color.Green;
  CheckedStyle.ForeColor = Color.White;
  UnCheckedStyle.BackColor = Color.White;
  UnCheckedStyle.ForeColor = Color.Black;
}

private void Form1_Load(object sender, EventArgs e) {
  GridDT = GetDatFromDB();
  AddCheckBoxColumnToTable(GridDT);
  dataGridView1.DataSource = GridDT;
}

private DataTable GetDatFromDB() {
  DataTable dt = new DataTable();
  dt.Columns.Add("GraficalFinal", typeof(string));
  Random rand = new Random();
  for (int i = 0; i < 10; i++) {
    if (rand.Next(2) == 0) {
      dt.Rows.Add("grafcheck");
    }
    else {
      dt.Rows.Add("");
    }
  }
  return dt;
}

private void AddCheckBoxColumnToTable(DataTable dt) {
  DataColumn col = new DataColumn("chkBxGrafica", typeof(bool), "IIF(GraficalFinal = 'grafcheck', 'true', 'false')");
  dt.Columns.Add(col);
}

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
  if (e.ColumnIndex == 1) {
    if (!dataGridView1.Rows[e.RowIndex].IsNewRow) {
      //Debug.WriteLine("DGV_CellFormatting <- Enter");
      if ((bool)dataGridView1.Rows[e.RowIndex].Cells[1].Value == true) {
        dataGridView1.Rows[e.RowIndex].Cells[1].Style = CheckedStyle;
      }
      else {
        dataGridView1.Rows[e.RowIndex].Cells[1].Style = UnCheckedStyle;
      }
      //Debug.WriteLine("DGV_CellFormatting -> Leave");
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM