DataGridViewComboBoxCell联动异常:如何规避值无效ArgumentException?
问题描述
我在使用DataGridView的两个DataGridViewComboBoxCell列时遇到问题:当更改某一行中列1的选项时,希望列2对应单元格的下拉列表项随之变更。默认状态下列2无选项,执行以下操作序列会触发异常:
- 在列1中选择“1”,触发col1Changed事件并更新列2的单元格选项;
- 在列2中选择“item1”;
- 尝试再次选择列1中的选项。
此时会触发如下异常:
DataGridView中发生以下异常:
System.ArgumentException: DataGridViewComboBoxCell值无效。
请处理DataError事件以替换此默认对话框。
问题代码如下:
void initaliseGrid() { string[] itemsCol1 = new string[] { "1", "2", "3" }; DataGridViewComboBoxColumn col1 = new DataGridViewComboBoxColumn(); col1.DropDownWidth = 200; col1.Width = 200; col1.MaxDropDownItems = 3; col1.HeaderText = "col 1"; col1.ReadOnly = false; dataGridView1.Columns.Insert(0, col1); col1.Items.AddRange(itemsCol1); DataGridViewComboBoxColumn col2 = new DataGridViewComboBoxColumn(); col2.DropDownWidth = 200; col2.Width = 200; col2.MaxDropDownItems = 3; col2.HeaderText = "col 2"; col2.ReadOnly = true; dataGridView1.Columns.Insert(1, col2); } int col1Idx = 0; int col2Idx = 1; private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { // Check if the curent cell is combobox if (dataGridView1.CurrentCell.ColumnIndex == colqIdx && e.Control is ComboBox) { ComboBox comboBox = e.Control as ComboBox; // Add an event when combobox index is changed comboBox.SelectedIndexChanged += col1Changed; } } private void col1Changed(object sender, EventArgs e) { var currentcell = dataGridView1.CurrentCellAddress; if (currentcell.X == col1Idx) { // Read the selected item string selectedItem = ((ComboBox)sender).SelectedItem.ToString(); // Get the cellfrom column 2 DataGridViewComboBoxCell comboBox = (DataGridViewComboBoxCell)dataGridView1.Rows[currentcell.X].Cells[col2Idx]; if (selectedItem == "1") { comboBox.Items.Clear(); comboBox.Items.Add("item1"); comboBox.Items.Add("item2"); comboBox.ReadOnly = false; } else if (selectedItem == "2") { comboBox.Items.Clear(); comboBox.Items.Add("item3"); comboBox.Items.Add("item4"); comboBox.ReadOnly = false; } else { comboBox.Items.Clear(); comboBox.ReadOnly = true; } } }
错误原因
异常核心原因:当再次修改列1选项时,列2单元格已选中的item1不在新的下拉选项集合中(比如选列1的"2"时,列2选项变为item3、item4;选"3"时列2选项被清空)。DataGridView会校验ComboBoxCell的当前值是否存在于其Items集合中,校验不通过就抛出参数异常。
此外代码还有两处错误:
dataGridView1_EditingControlShowing中的colqIdx是笔误,应为col1Idx;col1Changed中获取列2单元格时,dataGridView1.Rows[currentcell.X]错误,currentcell.X是列索引,应使用currentcell.Y(行索引)获取对应行。
解决方案
关键是更新列2的Items集合前,先清空该单元格的当前值,确保校验通过,同时修正代码中的笔误和索引错误:
修正后的完整代码
void initaliseGrid() { string[] itemsCol1 = new string[] { "1", "2", "3" }; DataGridViewComboBoxColumn col1 = new DataGridViewComboBoxColumn(); col1.DropDownWidth = 200; col1.Width = 200; col1.MaxDropDownItems = 3; col1.HeaderText = "col 1"; col1.ReadOnly = false; dataGridView1.Columns.Insert(0, col1); col1.Items.AddRange(itemsCol1); DataGridViewComboBoxColumn col2 = new DataGridViewComboBoxColumn(); col2.DropDownWidth = 200; col2.Width = 200; col2.MaxDropDownItems = 3; col2.HeaderText = "col 2"; col2.ReadOnly = true; dataGridView1.Columns.Insert(1, col2); } int col1Idx = 0; int col2Idx = 1; private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { // 修正笔误:colqIdx改为col1Idx if (dataGridView1.CurrentCell.ColumnIndex == col1Idx && e.Control is ComboBox) { ComboBox comboBox = e.Control as ComboBox; // 先移除已绑定事件,避免重复绑定导致多次触发 comboBox.SelectedIndexChanged -= col1Changed; comboBox.SelectedIndexChanged += col1Changed; } } private void col1Changed(object sender, EventArgs e) { var currentcell = dataGridView1.CurrentCellAddress; if (currentcell.X == col1Idx) { string selectedItem = ((ComboBox)sender).SelectedItem.ToString(); // 修正索引错误:currentcell.Y是行索引,不是currentcell.X DataGridViewComboBoxCell comboBoxCell = (DataGridViewComboBoxCell)dataGridView1.Rows[currentcell.Y].Cells[col2Idx]; // 关键步骤:先清空列2单元格的当前值 comboBoxCell.Value = null; comboBoxCell.Items.Clear(); if (selectedItem == "1") { comboBoxCell.Items.Add("item1"); comboBoxCell.Items.Add("item2"); comboBoxCell.ReadOnly = false; } else if (selectedItem == "2") { comboBoxCell.Items.Add("item3"); comboBoxCell.Items.Add("item4"); comboBoxCell.ReadOnly = false; } else { comboBoxCell.ReadOnly = true; } } }
额外优化建议
- 在
EditingControlShowing中先移除事件再添加,避免单元格多次进入编辑状态时重复绑定SelectedIndexChanged事件,导致一次选择触发多次col1Changed; - 若需保留列2的选中值(当新Items集合包含该值时),可先判断当前值是否存在于新集合,不存在再清空:
// 替换原清空Value的代码 string currentCol2Value = comboBoxCell.Value?.ToString(); comboBoxCell.Items.Clear(); // 先添加新选项 if (selectedItem == "1") { comboBoxCell.Items.Add("item1"); comboBoxCell.Items.Add("item2"); comboBoxCell.ReadOnly = false; } // ...其他分支 // 检查原值是否在新集合中,存在则保留,否则清空 if (!string.IsNullOrEmpty(currentCol2Value) && comboBoxCell.Items.Contains(currentCol2Value)) { comboBoxCell.Value = currentCol2Value; } else { comboBoxCell.Value = null; }
内容的提问来源于stack exchange,提问作者kmrydlx
相关产品推荐
相关产品推荐

