WinForms中ComboBox切换后DataGridView单元格格式失效求助
WinForms DataGridView 格式失效问题
首次选择ComboBox中的选项时,DataGridView的单元格格式可正常应用;但后续再次选择选项时,格式不再生效,单元格变为空白。
相关代码
int t = 0; foreach (DataGridViewRow row in dataGridView2.Rows) { row.Cells["toleranceMinDataGridViewTextBoxColumn"].Value = ""; row.Cells["toleranceNomDataGridViewTextBoxColumn"].Value = ""; row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Value = ""; row.Cells["toleranceMinDataGridViewTextBoxColumn"].ReadOnly = false; row.Cells["toleranceNomDataGridViewTextBoxColumn"].ReadOnly = false; row.Cells["toleranceMaxDataGridViewTextBoxColumn"].ReadOnly = false; } void creation() { dataGridView2.Columns.OfType<DataGridViewColumn>().ToList().ForEach(col => col.Visible = false); dataGridView2.Columns["lotDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["ItemDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["lotDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["ItemDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["toleranceMinDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["toleranceNomDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns["toleranceMaxDataGridViewTextBoxColumn"].Visible = true; dataGridView2.Columns[$"toleranceMinDataGridViewTextBoxColumn"].DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; dataGridView2.Columns[$"toleranceNomDataGridViewTextBoxColumn"].DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; dataGridView2.Columns[$"toleranceMaxDataGridViewTextBoxColumn"].DefaultCellStyle.BackColor = System.Drawing.Color.Wheat; } creation(); void creationitemsettolerances() { foreach (DataGridViewRow row in dataGridView2.Rows) { row.Visible = false; } foreach (DataGridViewRow row in dataGridView2.Rows) { if (!(row.Cells[$"{comboBox1.Text + comboBox2.Text}DataGridViewTextBoxColumn"].Value?.ToString() is "")) { row.Visible = true;; } } var result = from DataGridViewRow row in dataGridView2.Rows where row.Visible select row; foreach (DataGridViewRow row in result) { string[] splitter = new string[3]; t++; string a = row.Cells[$"{comboBox1.Text + comboBox2.Text}DataGridViewTextBoxColumn"].Value?.ToString(); if (a.Contains('-')) { splitter = a.Split('-'); row.Cells["toleranceMinDataGridViewTextBoxColumn"].Value = splitter[0]; row.Cells["toleranceNomDataGridViewTextBoxColumn"].Value = splitter[1]; try { row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Value = splitter[2]; }catch(Exception ex) { Debug.WriteLine(ex); } } else { row.Cells["toleranceNomDataGridViewTextBoxColumn"].Value = a; } } } creationitemsettolerances(); void formattagedestolerances() { var result = from DataGridViewRow row in dataGridView2.Rows where row.Visible select row; foreach (var row in result) { if ((row.Cells["toleranceMinDataGridViewTextBoxColumn"].Value?.ToString() is "") && (row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Value?.ToString() is "")) { string a = row.Cells["toleranceNomDataGridViewTextBoxColumn"].Value?.ToString(); var cell = (DataGridViewTextBoxCellEx)row.Cells["toleranceMinDataGridViewTextBoxColumn"]; cell.Value = a; cell.ColumnSpan = 3; cell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; } } } formattagedestolerances(); void definitiondeslots() { int deb1 = 0; int deb2 = 0; int fin1 = 0; int fin2 = 0; int deb3 = 0; int fin3 = 0; var result = from DataGridViewRow row in dataGridView2.Rows where row.Visible select row; fin3 = result.Count() ; foreach (var row in result) { if (row.Cells["TolerancesDataGridViewTextBoxColumn"].Value?.ToString() is "1") { if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "2") && (deb2 == 0)) { deb2 = row.Index; fin1 = row.Index - 1; } else if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "3") && (deb3 == 0)) { fin2 = row.Index - 1; deb3 = row.Index; } } else if(row.Cells["TolerancesDataGridViewTextBoxColumn"].Value?.ToString() is "2") { if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "1") && (deb1 == 0)) { deb1 = row.Index; } else if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "2") && (deb2 == 0)) { deb2 = row.Index; fin1 = row.Index - 1; } else if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "3") && (deb3 == 0)) { fin2 = row.Index - 1; deb3 = row.Index; } } else if (row.Cells["TolerancesDataGridViewTextBoxColumn"].Value?.ToString() is "3") { if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "1") && (deb1 == 0)) { deb1 = row.Index; } else if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "2") && (deb2 == 0)) { deb2 = row.Index; fin1 = row.Index - 1; } else if ((row.Cells["lotDataGridViewTextBoxColumn"].Value?.ToString() is "3") && (deb3 == 0)) { fin2 = row.Index - 1; deb3 = row.Index; } } } var cell1 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb1].Cells["lotDataGridViewTextBoxColumn"]; cell1.RowSpan = fin1 - deb1+1; var cell2 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb2].Cells["lotDataGridViewTextBoxColumn"]; cell2.RowSpan = fin2 - deb2+1; var cell3 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb3].Cells["lotDataGridViewTextBoxColumn"]; cell3.RowSpan = fin3 -deb3+2; } definitiondeslots(); void donneesdemesures() { listBox1.Items.Clear(); List<int> valeurs = new List<int>(); var result = from DataGridViewRow row in dataGridView2.Rows where row.Visible select row; foreach (var row in result) { string a = row.Cells[$"donnees{comboBox1.Text + comboBox2.Text}DataGridViewTextBoxColumn"].Value?.ToString(); if (!(a is "")) { valeurs.Add(Convert.ToInt32(a)); } listBox1.Items.Add(a); } int b = valeurs.Max(); for (int i = 1; i <= b; i++) { dataGridView2.Columns.Add($"Test{i}", "Donnee"); } foreach (var row in result) { for (int i = 1; i <= b; i++) { row.Cells[$"Test{i}"] = new DataGridViewTextBoxCellEx(); } } int m = 0; foreach (var row in result) { for (int i = 1; i <= b; i++) { row.Cells[$"Test{i}"].Style.BackColor = System.Drawing.Color.Gray; } for (int i = 1; i <= valeurs[m]; i++) { row.Cells[$"Test{i}"].Style.BackColor = System.Drawing.Color.White; } m++; } } donneesdemesures();
问题排查与修复方案
核心问题点
- 单元格合并状态未重置:二次选择时,之前设置的
ColumnSpan/RowSpan残留,导致单元格布局混乱 - 动态列重复添加:每次执行
donneesdemesures()都会新增Test系列列,列数量不断累积破坏布局 - 自定义单元格状态残留:
DataGridViewTextBoxCellEx的合并属性未在每次操作前初始化 - 索引越界风险:
definitiondeslots()中未判断deb1/deb2/deb3的有效性,可能引发空引用异常
具体修复步骤
1. 重置单元格合并与样式
在每次操作开始时,遍历所有单元格清除之前的合并状态和自定义样式:
foreach (DataGridViewRow row in dataGridView2.Rows) { foreach (DataGridViewCell cell in row.Cells) { cell.ColumnSpan = 1; cell.RowSpan = 1; cell.Style = new DataGridViewCellStyle(); // 重置为默认样式 } // 原有的清空值和ReadOnly设置... }
2. 清理重复动态列
在donneesdemesures()开头移除之前添加的Test列,避免重复添加:
void donneesdemesures() { // 先删除历史Test列 for (int i = dataGridView2.Columns.Count - 1; i >= 0; i--) { if (dataGridView2.Columns[i].Name.StartsWith("Test")) { dataGridView2.Columns.RemoveAt(i); } } // 原有的listBox清空等逻辑... }
3. 修复单元格合并逻辑
在formattagedestolerances()中确保单元格类型正确,并处理显示状态:
void formattagedestolerances() { var result = from DataGridViewRow row in dataGridView2.Rows where row.Visible select row; foreach (var row in result) { bool minEmpty = string.IsNullOrEmpty(row.Cells["toleranceMinDataGridViewTextBoxColumn"].Value?.ToString()); bool maxEmpty = string.IsNullOrEmpty(row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Value?.ToString()); if (minEmpty && maxEmpty) { string a = row.Cells["toleranceNomDataGridViewTextBoxColumn"].Value?.ToString(); var minCell = row.Cells["toleranceMinDataGridViewTextBoxColumn"]; // 确保是自定义单元格类型 if (!(minCell is DataGridViewTextBoxCellEx)) { minCell = new DataGridViewTextBoxCellEx(); row.Cells["toleranceMinDataGridViewTextBoxColumn"] = minCell; } ((DataGridViewTextBoxCellEx)minCell).Value = a; ((DataGridViewTextBoxCellEx)minCell).ColumnSpan = 3; ((DataGridViewTextBoxCellEx)minCell).Style.Alignment = DataGridViewContentAlignment.MiddleCenter; // 隐藏另外两个单元格避免重叠 row.Cells["toleranceNomDataGridViewTextBoxColumn"].Visible = false; row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Visible = false; } else { // 恢复三个单元格的显示 row.Cells["toleranceNomDataGridViewTextBoxColumn"].Visible = true; row.Cells["toleranceMaxDataGridViewTextBoxColumn"].Visible = true; } } }
4. 避免索引越界
在definitiondeslots()中添加有效性判断,防止空引用:
void definitiondeslots() { // 原有的变量初始化和遍历逻辑... // 添加索引有效性判断 if (deb1 >= 0 && deb1 < dataGridView2.Rows.Count && fin1 >= deb1) { var cell1 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb1].Cells["lotDataGridViewTextBoxColumn"]; cell1.RowSpan = fin1 - deb1 + 1; } if (deb2 >= 0 && deb2 < dataGridView2.Rows.Count && fin2 >= deb2) { var cell2 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb2].Cells["lotDataGridViewTextBoxColumn"]; cell2.RowSpan = fin2 - deb2 + 1; } if (deb3 >= 0 && deb3 < dataGridView2.Rows.Count && fin3 >= deb3) { var cell3 = (DataGridViewTextBoxCellEx)dataGridView2.Rows[deb3].Cells["lotDataGridViewTextBoxColumn"]; cell3.RowSpan = fin3 - deb3 + 2; } }
内容的提问来源于stack exchange,提问作者LiterallyGutsFromBerserk
相关产品推荐
相关产品推荐

