DataGridViewComboBoxCell无法正常工作 [英] DataGridViewComboBoxCell not working right
问题描述
我在下面有一个非常简单的示例应用程序。这适用于Windows窗体,并且应该具有在Designer中创建的匹配,其中DataGridView具有两列:Name和Department。 Department是一个DataGridViewComboBoxCell。
网格按预期列出数据,组合框按预期列出其项目。但是,我无法将组合框中选择的数据绑定到网格的DataBoundItem。例如,当应用程序首次启动时,我唯一的Person对象具有DepartmentID = 2,它与组合框中的值匹配,但在组合框中未选择任何内容。当在组合框中选择了某些内容时,它不会反映在Person对象中。
有一条注释掉的代码行用于设置ValueMember,但是这会导致不存在名为DeptID的字段错误。
两个数据集都是ArrayList而不是DataTable非常重要。
如何完成行数据和组合框选择之间的绑定?
---完整的项目代码如下---
I have a very simple sample application below. This is for Windows Forms, and should have a matching for created in Designer with a DataGridView that has two columns: Name, and Department. Department is a DataGridViewComboBoxCell.
The grid lists data as expected, and the combo-box list its items as expected. However, I cannot get the data selected in the combo-box tied to the DataBoundItem of the grid. For example, when the app first starts, my only Person object has a DepartmentID = 2, which matches a value in the combo-box, but nothing is selected in the combo-box. When something is selected in the combo-box, it does not get reflected in the Person object.
There is a commented-out line of code for setting ValueMember, but this causes a "Field called DeptID does not exist" error.
It is important that both data sets are ArrayList and not DataTable.
How do I complete the binding between row data and combo-box selection?
--- Full project code is below ---
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestApp
{
public partial class Form1 : Form
{
private ArrayList personList = new ArrayList();
private ArrayList deptList = new ArrayList();
BindingSource m_BindSource = new BindingSource();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
personList.Add(new Person("Tim", 2));
deptList.Add(new Department("A", 1));
deptList.Add(new Department("B", 2));
deptList.Add(new Department("C", 3));
DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)grid1.Columns[1].CellTemplate;
cell.DataSource = deptList;
cell.DisplayMember = "DeptName";
//cell.ValueMember = "DeptID"; // "Field called DeptID does not exist"
try
{
m_BindSource.DataSource = null;
m_BindSource.DataSource = personList;
grid1.DataSource = m_BindSource;
}
catch (Exception ex)
{
ex.GetType();
MessageBox.Show(ex.Message);
}
}
}
public class Person
{
public Person(String name, int deptID)
{
PersonName = name;
DepartmentID = deptID;
}
private String m_PersonName;
public String PersonName
{
get { return m_PersonName; }
set { m_PersonName = value; }
}
private int m_DepartmentID;
public int DepartmentID
{
get { return m_DepartmentID; }
set { m_DepartmentID = value; }
}
}
public class Department
{
public Department(String name, int deptID)
{
DeptName = name;
DepartmentID = deptID;
}
private String m_DeptName;
public String DeptName
{
get { return m_DeptName; }
set { m_DeptName = value; }
}
private int m_DepartmentID;
public int DepartmentID
{
get { return m_DepartmentID; }
set { m_DepartmentID = value; }
}
}
}
推荐答案
经过大量研究和修补,我找到了解决方案。下面是Form1_Load()的主体。该解决方案分为两部分:
1)不要动态创建单元格/列,只需将其构建到设计时视图中并适当绑定为如下所示:catch()语句
2)网格不会像我习惯的那样自动将行数据与组合框数据进行匹配。最后的for循环遍历并将现有的行数据选择绑定到组合框中的相应条目。
作为补充说明,我发现这个解决方案如果DataGridView位于选项卡控件中,则会出现其他问题。如果网格位于第一个选项卡以外的任何选项卡上,则行/组合框绑定将失败。这是否是一个MS错误我不知道,但解决方案是将for循环放在选项卡控件的SelectedIndexChanged()事件中的下面的代码中,并在更改为相关选项卡时运行它。 br $>
After much research and tinkering, I found the solution. Below is the body of Form1_Load() that works. There are two parts to the solution:
1) Instead of creating the cell/column on the fly, just build it into the design-time view and bind appropriately as shown below the catch() statement
2) The grid will not automatically match up row data with combobox data as I am used to. The for-loop at the end goes through and binds the existing row data selection to the corresponding entry in the combobox.
As an additional note, I found that this solution has additional problems if the DataGridView is located in a tab control. If the grid is on any tab other than the first one, the row/combobox binding will fail. Whether this is a MS bug or not I don't know, but the solution was to put the for-loop in the code below in the SelectedIndexChanged() event for the tab control and run it when changing to the tab in question.
personList.Add(new Person("Tim", 2)); // Create one Person data object and add it to the list used by the DataGridView
// Create a list of Departments to be used by the combo box in the DataGridView
deptList.Add(new Department("A", 1));
deptList.Add(new Department("B", 2));
deptList.Add(new Department("C", 3));
grid1.AutoGenerateColumns = false; // If we don't do this, the DepartmentID shows up as an additional column
try // Bind the Person list to the DataGridView
{
m_BindSource.DataSource = null;
m_BindSource.DataSource = personList;
grid1.DataSource = m_BindSource;
}
catch (Exception ex)
{
ex.GetType();
MessageBox.Show(ex.Message);
}
// Bind the Department data to the appropriate column in the DataGridView
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).DataSource = deptList;
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).DisplayMember = "DeptName";
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).ValueMember = "DeptID";
// Since the DataGridView won't automatically sync the Department list with each Person's DepartmentID, we have to manually link the two. This is what
// causes the combo box to show the proper selection for each Person's Department in the grid of existing data.
foreach (DataGridViewRow row in grid1.Rows)
{
if (row.DataBoundItem != null)
{
row.Cells["Department"].Value = ((Person)row.DataBoundItem).DepartmentID;
}
}
这篇关于DataGridViewComboBoxCell无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!