[英]Populating datagridview winforms .net 4.0
I am having problems in loading a datagridview with 2 columns. 我在使用2列加载datagridview时遇到问题。 Form with a Datagridview and 1 button.
表格带有Datagridview和1个按钮。
Department (text) EmployeesByDpt( Combo) 部门(文字)EmployeesByDpt(Combo)
I have a form with a datagridview and a Button (Load),when I press load the datagridview should be populated. 我有一个带有datagridview和Button(Load)的表单,当我按下load时,应该填充datagridview。 clicking on the Employee Combo should display all the employees that belong to a particular department.
单击Employee Combo应显示属于特定部门的所有员工。
I cannot seem to get it to work ,below is what I have done, 我似乎无法让它工作,下面就是我所做的,
Any suggestions?At the moment nothing shows. 有什么建议吗?目前没什么可说的。 Thanks
谢谢
Code (for semplicity I have put all together) 代码(为了简单起见,我把所有内容放在一起)
public partial class Form2 : Form
{
Repository repository;
readonly DataGridViewTextBoxColumn colDepartment=new DataGridViewTextBoxColumn();
readonly DataGridViewComboBoxColumn colComboEmployeesByDpt = new DataGridViewComboBoxColumn();
public Form2()
{
InitializeComponent();
repository = new Repository();
SetupDataGridView();
}
private void SetupDataGridView()
{
dataGridView1.EditingControlShowing += OnEditingControlShowing;
dataGridView1.CellValueChanged += OnCellsValueChanged;
dataGridView1.AutoGenerateColumns = false;
colDepartment.DataPropertyName = "Name";
colDepartment.HeaderText = "Department Name";
colComboEmployeesByDpt.DataPropertyName = "Employees";
colComboEmployeesByDpt.HeaderText = "Employees";
colComboEmployeesByDpt.DisplayMember = "FullName";
//colComboEmployeesByDpt.DataSource = "FullName";
dataGridView1.Columns.AddRange(new DataGridViewColumn[] { colDepartment ,colComboEmployeesByDpt});
}
private void OnCellsValueChanged(object sender, DataGridViewCellEventArgs e)
{
}
private void OnEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView1.CurrentCell.ColumnIndex == colDepartment.Index)
{
var control = e.Control as DataGridViewComboBoxEditingControl;
if (control != null)
{
var bs = control.DataSource as BindingSource;
if (bs != null)
{
var comboBox = e.Control as ComboBox;
BindingList<Employee> employees = repository.GetEmployeeByDepartments(control.Text);
comboBox.DataSource = employees;
object employeeValue = dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[colComboEmployeesByDpt.Index].Value;
if (employeeValue == DBNull.Value || employeeValue == null)
if (dataGridView1.CurrentCell.Value != DBNull.Value && dataGridView1.CurrentCell.Value != null)
{
control.SelectedValue = dataGridView1.CurrentCell.Value;
}
}
}
}
}
private void btnLoad_Click(object sender, EventArgs e)
{
BindingList<Department> departments = repository.GetDepartments();
dataGridView1.DataSource = departments;
dataGridView1.Refresh();
}
}
public class Department
{
public Department()
{
Employees=new BindingList<Employee>();
}
public string Name { get; set; }
public BindingList<Employee> Employees { get; set; }
}
public class Employee
{
public string FullName { get; set; }
}
public class Repository
{
public BindingList<Department> GetDepartments()
{
var departments=new BindingList<Department>();
departments.Add(new Department{Name = "Food"});
departments.Add(new Department{Name = "Travel"});
departments.Add(new Department{Name = "Beauty"});
return departments;
}
public BindingList<Employee> GetEmployeeByDepartments(string name)
{
var employees = new BindingList<Employee>();
switch (name)
{
case "Food":
employees.Add(new Employee { FullName = "Jim Bloggs1" });
employees.Add(new Employee { FullName = "Jim Bloggs2" });
break;
case "Travel":
employees.Add(new Employee { FullName = "Marc Smith1" });
employees.Add(new Employee { FullName = "Marc Smith2" });
break;
case "Beauty":
employees.Add(new Employee { FullName = "Mario XXX1" });
employees.Add(new Employee { FullName = "Mario XXX2" });
break;
}
return employees;
}
}
Running your exact code, I ran into several problems. 运行您的确切代码,我遇到了几个问题。 The following explanation will show you what I did to fix each subsequent problem but with a warning: In the end I couldn't make a selection from the
ComboBox
without changing the binding method between the DataGridView
and the Departments
and dropping some provided code. 下面的解释将向您展示我为解决每个后续问题所做的工作,但有一个警告:最后,我无法在不更改
DataGridView
和Departments
之间的绑定方法并删除一些提供的代码的情况下从ComboBox
进行选择。
ArgumentException thrown for each row 为每一行抛出ArgumentException
Each row was throwing the exception: "DataGridViewComboBoxCell value is not valid." 每行抛出异常: “DataGridViewComboBoxCell值无效。” Changing the following line fixed this:
更改以下行修复此问题:
colComboEmployeesByDpt.DataPropertyName = "Employees";
to 至
colComboEmployeesByDpt.DataPropertyName = "Employee";
Empty ComboBoxes 空组合框
Now you'll notice the ComboBoxes are all empty. 现在你会注意到ComboBox都是空的。 In the event handler
OnEditingControlShowing
the first if statement
should check against colComboEmployeesByDpt.Index
instead of colDepartment.Index
. 在事件处理程序
OnEditingControlShowing
,第一个if statement
应该检查colComboEmployeesByDpt.Index
而不是colDepartment.Index
。 But that's not enough because if (bs != null)
will always be false. 但这还不够,因为
if (bs != null)
总是假的。 Even fixing that check, control.Text
is always empty. 即使修复该检查,
control.Text
也总是空的。 Instead, try: 相反,尝试:
BindingList<Employee> employees = repository.GetEmployeeByDepartments(this.dataGridView1.CurrentRow.Cells[colDepartment.Index].Value.ToString());
With this, you'll see each ComboBox
has the correct list of employee names. 有了这个,您将看到每个
ComboBox
都有正确的员工姓名列表。 However, the ArgumentException
has returned. 但是,
ArgumentException
已返回。 Try as I might, I couldn't fix it this time. 尽我所能,这次我无法修复它。 (I suspect the
ComboBox
items lists were always empty, so the selected value was "invalid" .) (我怀疑
ComboBox
项目列表始终为空,因此所选值为“无效” 。)
Answer - Restructure 答案 - 重组
To get it to work I made several core changes. 为了让它工作,我做了几个核心的改变。 I completely dropped the following:
我完全放弃了以下内容:
colComboEmployeesByDpt.DisplayMember = "FullName";
private void OnEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
...
}
Then I added a public property to remember the Departments, manually bound each row's employees, and hooked-up OnCellsValueChanged
to refresh the lists when the Department Name changed: 然后我添加了一个公共属性来记住Departments,手动绑定每一行的员工,并在部门名称更改时连接
OnCellsValueChanged
以刷新列表:
BindingList<Department> Departments { get; set; }
private void OnCellsValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == colDepartment.Index)
{
this.Departments[e.RowIndex].Employees = repository.GetEmployeeByDepartments(this.dataGridView1.CurrentCell.EditedFormattedValue.ToString());
DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)this.dataGridView1.CurrentRow.Cells[colComboEmployeesByDpt.Index];
cell.DataSource = this.Departments[e.RowIndex].Employees;
}
}
private void btnLoad_Click(object sender, EventArgs e)
{
//this.dataGridView1.Rows.Clear(); // Needed if the button can be clicked repeatedly.
this.Departments = repository.GetDepartments();
foreach (Department department in this.Departments)
{
department.Employees = repository.GetEmployeeByDepartments(department.Name);
DataGridViewRow row = (DataGridViewRow)(dataGridView1.Rows[0].Clone());
DataGridViewTextBoxCell textCell = (DataGridViewTextBoxCell)(row.Cells[0]);
textCell.Value = department.Name;
DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)(row.Cells[1]);
comboCell.DataSource = department.Employees;
comboCell.DisplayMember = "FullName";
dataGridView1.Rows.Add(row);
}
}
This solution worked for me. 这个解决方案对我有用。 When I have free time I will continue to look into fixing your original solution from the point that stumped me.
当我有空闲时间时,我将继续从困难的地方开始研究修复原始解决方案。 Hope this helps for now.
希望现在有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.