Windows Forms中C#实现DataGridViewComboBoxColumn取值与联动的方法
嘿,我来帮你搞定这两个问题!咱们一步步拆解,先解决联动下拉列的需求,再搞定获取选中值的事儿~
一、实现DataGridViewComboBoxColumn的联动效果
首先你得先把关联数据准备好——毕竟要实现“选A显示对应B”,得先有A和B的映射关系。我用字典来存账户和对应的联系人列表,你可以替换成自己的实际数据:
// 准备关联数据:账户 → 对应联系人列表 Dictionary<string, List<string>> accountContacts = new Dictionary<string, List<string>>() { {"账户A", new List<string>{"联系人A1", "联系人A2"}}, {"账户B", new List<string>{"联系人B1", "联系人B2", "联系人B3"}}, {"账户C", new List<string>{"联系人C1"}} };
接下来创建两个下拉列,第一个列绑定账户列表,第二个列先绑定空列表(后续动态更新):
// 创建第一个「账户」下拉列 DataGridViewComboBoxColumn cmbAccounts = new DataGridViewComboBoxColumn(); cmbAccounts.Name = "Accounts"; cmbAccounts.HeaderText = "账户"; // 绑定账户列表(字典的Key集合) cmbAccounts.DataSource = new List<string>(accountContacts.Keys); dataGridView1.Columns.Add(cmbAccounts); // 创建第二个「联系人」下拉列 DataGridViewComboBoxColumn cmbContacts = new DataGridViewComboBoxColumn(); cmbContacts.Name = "Contacts"; cmbContacts.HeaderText = "联系人"; // 初始绑定空列表,后续根据账户选择动态更新 cmbContacts.DataSource = new List<string>(); dataGridView1.Columns.Add(cmbContacts);
然后是联动的核心:监听第一个下拉列的选中变化,实时更新当前行的联系人下拉数据源。我们需要用EditingControlShowing事件(单元格进入编辑状态时触发):
// 绑定DataGridView的编辑控件显示事件 dataGridView1.EditingControlShowing += (sender, e) => { // 判断当前编辑的是「账户」列 if (dataGridView1.CurrentCell.OwningColumn.Name == "Accounts") { // 获取当前的下拉控件 if (e.Control is ComboBox comboBox) { // 先移除旧的选中事件,避免重复触发 comboBox.SelectedIndexChanged -= ComboBox_SelectedIndexChanged; // 添加新的选中事件 comboBox.SelectedIndexChanged += ComboBox_SelectedIndexChanged; } } }; // 账户下拉列选中变化时的处理逻辑 private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (sender is ComboBox comboBox && comboBox.SelectedItem != null) { string selectedAccount = comboBox.SelectedItem.ToString(); // 获取当前编辑的行 DataGridViewRow currentRow = dataGridView1.CurrentRow; if (currentRow != null && accountContacts.ContainsKey(selectedAccount)) { // 拿到当前行的联系人下拉单元格 DataGridViewComboBoxCell contactCell = (DataGridViewComboBoxCell)currentRow.Cells["Contacts"]; // 更新联系人下拉的数据源 contactCell.DataSource = new List<string>(accountContacts[selectedAccount]); // 清空之前的选中值,避免残留旧数据 contactCell.Value = null; } } }
最后可以加个CellEndEdit事件,确保选中值被正确提交到单元格:
dataGridView1.CellEndEdit += (sender, e) => { if (e.ColumnIndex == dataGridView1.Columns["Accounts"].Index) { dataGridView1.BeginEdit(false); } };
二、获取ComboBox列的选中值
获取选中值分两种场景,你可以根据需求选:
1. 实时获取(用户选中时立即触发)
绑定CellValueChanged事件,当单元格值变化时直接获取:
dataGridView1.CellValueChanged += (sender, e) => { // 排除新增行 if (dataGridView1.Rows[e.RowIndex].IsNewRow) return; // 判断是账户列还是联系人列 if (e.ColumnIndex == dataGridView1.Columns["Accounts"].Index) { string selectedAccount = dataGridView1.Rows[e.RowIndex].Cells["Accounts"].Value?.ToString() ?? "未选择"; // 这里可以替换成你的业务逻辑,比如打印、存数据库等 MessageBox.Show($"选中的账户:{selectedAccount}"); } else if (e.ColumnIndex == dataGridView1.Columns["Contacts"].Index) { string selectedContact = dataGridView1.Rows[e.RowIndex].Cells["Contacts"].Value?.ToString() ?? "未选择"; MessageBox.Show($"选中的联系人:{selectedContact}"); } };
2. 批量获取(比如点击按钮时获取所有行的选中值)
如果需要一次性获取所有行的选择结果,可以在按钮点击事件里遍历行:
private void btnGetAllValues_Click(object sender, EventArgs e) { foreach (DataGridViewRow row in dataGridView1.Rows) { // 跳过新增行 if (row.IsNewRow) continue; string account = row.Cells["Accounts"].Value?.ToString() ?? "未选择"; string contact = row.Cells["Contacts"].Value?.ToString() ?? "未选择"; // 输出结果,这里可以替换成你的业务逻辑 Console.WriteLine($"行{row.Index}:账户={account},联系人={contact}"); } }
注意事项
- 如果你用的是实体类而非字符串,记得给
DataGridViewComboBoxColumn设置DisplayMember(显示的文本)和ValueMember(实际绑定的值); - 处理空值时用
?.ToString()和??空合并运算符,避免空引用异常; - 可以根据自己的实际数据源替换示例中的
accountContacts字典。
内容的提问来源于stack exchange,提问作者Frederico Eglesias
相关产品推荐
相关产品推荐

