簡體   English   中英

如何更改 datagridview 特定的復選框單元格顏色並根據數據庫值進行檢查?

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

我有一個帶有復選框列的 datagridview。 復選框單元格應根據數據庫表列中的特定值更改顏色並檢查狀態。 如果該值為“grafcheck”,則復選框單元格和復選框應為綠色並選中。 如果表中的字段為 null,則復選框單元格應為白色且未選中。 下面的代碼做了它應該做的,但它標記為選中每個復選框並使它們全部變為綠色,無論該值是否存在。

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();
            }

您可能想在這里重新考慮您的方法。 首先你說代碼運行后,所有的復選框都被選中並且是綠色的。 從我所見,這是有道理的,因為查詢只獲取行… WHERE GraficaFinal='grafcheck' ……因此,如果您從查詢中獲取數據……那么所有行都將具有grafcheck 這幾乎使... if (graph == "grafcheck") {.. ... 語句變得多余。

另一個問題...,... while (reader.Read()) { … ...循環正在遍歷讀取的行,因此代碼讀取一行,然后將graph變量設置為...

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

這很好......但是......然后代碼(出於某種未知原因)“循環”通過網格中的所有行......? ……這不可能。 基本上,當使用for循環遍歷網格的行時會發生什么情況,會將每行復選框 state 設置為“當前”線graph值……無論該行的GraficaFinal單元格中的實際值是什么。 但是我們已經知道它將是“grafcheck”。

如果您跟蹤此代碼,它將基本上將所有復選框值和顏色設置為數據中最后一行包含的任何內容。 換句話說……我相信您不希望在那里有一個for循環,您只會在該行中設置一 (1) 個值。 這就引出了“為什么”代碼“手動”將值添加到網格中? 我相信您可以使用DataTable並直接從查詢中填充它。 然后,您可以簡單地將DataTable用作網格的DataSource 填寫表格的代碼可能類似於……

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

這將根據您的查詢用一列GraficalFinal數據填充表。

另外……目前尚不清楚ComNef網格中的chkbxGrafica列來自“哪里”……我假設您在設計器中添加該列,或者可能在某些未顯示的代碼中添加該列。 如果您要手動將列添加到 GRID 中,那么有一種更簡單的方法。

我建議您手動將列添加到我們之前從 DB 查詢中獲得的DataTable中,而不是手動將列添加到 GRID。 這對於將列添加到 GRID 還是 TABLE 可能顯得微不足道……但是,GRID 列無法在其列中使用“表達式”。 DataTable允許列包含“表達式”……

DataColumn.Expression 屬性

如果我們想將chkbxGrafica單元格設置為選中或未選中 state,這將非常方便。 這個表達式可能看起來像……

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

這將“自動”將復選框單元格設置為正確的檢查 state。 注意……因為復選框列是“表達式”列……那么用戶將無法直接更改復選框 state,但是……更改GraficaFinal單元格將更改復選框 state。 “表達式”列的這一簡單代碼將消除所有循環通過網格並設置復選框值的代碼。

此外……一旦代碼運行並且用戶將GraficalFinal單元格值“更改”為grafcheck以外的任何值……那么……該行上的復選框將自動變為“未選中”。 顯然,如果單元格值是“grafcheck”,那么這會將復選框設置為“選中”

不幸的是,這不會像你想要的那樣給單元格“着色”。 為此,我們將需要查看 GRID。 Ňɏssa Pøngjǣrdenlarp 評論了一個鏈接,它是為網格單元着色的許多可能方法之一。 更改單元格顏色的最常見和最直觀的網格事件是網格CellFormatting事件。 當單元格需要格式化時,該事件將觸發,在這種情況下,我們可以簡單地檢查復選框值是什么,然后適當地為它着色。

需要注意的是……使用網格CellFormatting事件效果很好,但是,如果您將Debug語句放入事件中……您會注意到該事件將觸發比需要的次數多得多的次數。 例如,當用戶簡單地將 cursor 移動到網格中的單元格上時,它可能會觸發。 這是我可能會選擇不同事件(如網格CellValueChanged事件)的原因之一。

不幸的是,這為更多工作打開了大門,因為當設置了網格DataSource時,該事件不會觸發。 當設置網格DataSource時,將觸發CellFormatting事件。 所以……如果我們使用網格CellValueChanged事件而不是網格CellFormatting事件……那么……我們最終會陷入我們已經身處的同一條船上……我們將需要實現添加代碼以“循環”遍歷 GRID 中的所有行並在設置網格DataSource后立即設置單元格 colors。 當然,這消除了單元格在不需要時被格式化,但是,它為您創造了更多的工作。 在下面的示例中……我將使用網格CellFormatting事件。

所以……總結一下……在DataTable中添加一個帶有“表達式”的 Boolean 類型列。 這將根據GraficalFinal單元格包含的內容設置復選框值。 然后連接網格CellFormatting事件以設置單元格顏色。

下面的代碼演示了上述內容的一個小而完整的示例。 注意…顯然GetDataFromDB方法只是創建一個帶有一些隨機值的單列表,您可以更改此代碼以從您的數據庫中獲取GraficaFinal表。 如果您將DataGridView拖放到表單上並連接其CellFormatting事件,則代碼應生成以下內容。 祝你好運。

在此處輸入圖像描述

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");
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM