DataGrid 中的 ComboBox






3.38/5 (37投票s)
如何在 DataGrid 中嵌入 ComboBox (DropDownList)。
引言
我需要在我的 DataGrid
中使用 ComboBox
。在网上搜索后,我找到了很多示例,但没有一个对我有效。
从 The Code Project 上 Alastair Stells 的文章和我在互联网上找到的其他资料中获得灵感,我制作了以下 DataGridComboBoxColumn
类。
为什么其他示例不起作用
所有其他示例都使用 DataView
填充 ComboBox
,但我需要(想要能够)使用 IList
(ArrayList
) 而不是 DataView
来填充我的 ComboBox
。
columnComboBox = new DataGridComboBoxColumn();
columnComboBox.comboBox.DataSource = new ArrayList(MyDataClass.GetArray());
columnComboBox.comboBox.DisplayMember = "Name";
columnComboBox.comboBox.ValueMember = "GUID";
并且 MyDataClass.GetArray()
返回 MyDataClass[]
,并具有两个名为 Name
和 GUID
的属性。
其他示例期望 columnComboBox.comboBox.DataSource
是一个 DataView
,而它是一个 ArrayList
则会生成异常。
我使用 ComboBox 来获取显示文本
由于您不知道 columnComboBox.comboBox.DataSource
的类型,因此您无法使用它来在底层数据和 DataGrid
中显示的内容之间进行转换。
相反,我通过重写 ComboBox
并实现此方法来使用 ComboBox
本身。
public string GetDisplayText(object value) {
// Get the text.
string text = string.Empty;
int memIndex = -1;
try {
base.BeginUpdate();
memIndex = base.SelectedIndex;
base.SelectedValue = value.ToString();
text = base.SelectedItem.ToString();
base.SelectedIndex = memIndex;
} catch {
return GetValueText(0);
} finally {
base.EndUpdate();
}
return text;
} // GetDisplayText
我所做的事情很简单。我选择显示我想要的文本的项目,获取文本,然后重新选择原始项目。 通过这种方式,使用什么数据源都没有关系。
因为我使用 ComboBox
本身来获取显示文本,所以必须在绘制 DataGrid
之前填充 ComboBox
。
Alastair Stells 在他的文章中提到了这一点
出现的另一个问题令人大开眼界! 我发现
ComboBox
在第一次设置ComboBox.Visible
属性之前不会被填充。
这意味着 ComboBox
不能用于获取初始显示文本,因为它在首次显示(绘制)DataGrid
时不可见。
我使用了一个普通的 ComboBox
来演示问题和解决方案。
ComboBox comboBox = new ComboBox();
comboBox.DataSource = new ArrayList(MyDataClass.GetArray());
comboBox.DisplayMember = "Name"
comboBox.ValueMember = "GUID"
MessageBox.Show(comboBox.Items.Count.ToString()); // THIS IS ALWAYS 0!
我了解到显示 ComboBox
没有帮助,但我必须设置它的父级 - 这会在内部将数据从 DataSource
提交到 Items
集合。
ComboBox comboBox = new ComboBox();
comboBox.Parent = this; // this is a Form instance in my case.
comboBox.DataSource = new ArrayList(MyDataClass.GetArray());
comboBox.DisplayMember = "Name"
comboBox.ValueMember = "GUID"
// THIS IS MyDataClass.GetArray().Count
MessageBox.Show(comboBox.Items.Count.ToString());
关于我的 DataGridComboBoxColumn 的其他内容
源代码很简单。首先,我继承了 DataGridTextBoxColumn
,但我的类随后演变为继承 DataGridColumnStyle
。 这意味着我必须实现 Paint
方法,但在这一点上,我也有一些例子。我喜欢所有背后都没有不可见的 TextBox
的想法。
如何使用
遗憾的是,我不知道如何使用 GridColumnStyle
s“注册”我的 DataGridComboBoxColumn
,使我能够在设计器中设计 DataGrid
列。 此代码是手动完成的
// Add three MyDataClass objects, to the DataGridComboBox.
// This is the choices which will apear in the ComboBox in the DataGrid.
// You can see in the source that the MyDataClass doubles
// as a static collection, where the new MyDataClass objects
// automatically is added.
// All the MyDataClass objects can be retreived in an array
// with the static method: MyDataClass.GetArray().
if (MyDataClass.GetArray().Length == 0) {
new MyDataClass("Denmark");
new MyDataClass("Faroe Islands (DK)");
new MyDataClass("Finland");
new MyDataClass("Greenland (DK)");
new MyDataClass("Iceland");
new MyDataClass("Norway");
new MyDataClass("Sweden");
}
// I don't have a database here, so I make my
// own DataTable with two columns and finally
// populate it with some test rows.
DataTable table = new DataTable("TableOne");
DataColumn column = table.Columns.Add();
column.ColumnName = "country";
// Realy a GUID from the DataGridComboBox.
column.DataType = Type.GetType("System.Guid");
column = table.Columns.Add();
column.ColumnName = "notes";
column.DataType = Type.GetType("System.String");
table.Rows.Add(new object[] {MyDataClass.GetArray()[0].GUID,
"Population 5.368.854"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[1].GUID,
"Population 46.011"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[2].GUID,
"Population 5.183.545"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[3].GUID,
"Population 56.376"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[4].GUID,
"Population 279.384"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[5].GUID,
"Population 4.525.116"});
table.Rows.Add(new object[] {MyDataClass.GetArray()[6].GUID,
"Population 8.876.744"});
// Create a DataGridTableStyle object.
DataGridTableStyle tableStyle = new DataGridTableStyle();
DataGridTextBoxColumn columnTextBox;
DataGridComboBoxColumn columnComboBox;
tableStyle.RowHeadersVisible = true;
tableStyle.RowHeaderWidth = 20;
// Add customized columns.
// Column "notes", which is a simple text box.
columnTextBox = new DataGridTextBoxColumn();
columnTextBox.MappingName = "notes";
columnTextBox.HeaderText = "Country notes";
columnTextBox.Width = 200;
tableStyle.GridColumnStyles.Add(columnTextBox);
// Column "country", which is the ComboBox.
columnComboBox = new DataGridComboBoxColumn();
columnComboBox.comboBox.Parent = this; // Commit dataset.
columnComboBox.comboBox.DataSource =
new ArrayList(MyDataClass.GetArray());
columnComboBox.comboBox.DisplayMember = "name";
columnComboBox.comboBox.ValueMember = "GUID";
columnComboBox.MappingName = "country";
columnComboBox.HeaderText = "Country";
columnComboBox.Width = 200;
tableStyle.GridColumnStyles.Add(columnComboBox);
// Add the custom TableStyle to the DataGrid.
datagrid.TableStyles.Clear();
datagrid.TableStyles.Add(tableStyle);
datagrid.DataSource = table;
tableStyle.MappingName = "TableOne";
我认为我在这里关注了一个问题:如果您想在您的 DataGrid
中使用 ComboBox
,并且您想使用包含您自己的类实例的数组中的项目填充 ComboBox
。
我希望有人觉得它有用 - 享受。
2006 年 9 月更新
在我的源代码中发现了一些错误。 显然,即使 .NET 2.0 已经解决了 DataGrid
中 ComboBox
的问题,仍然有人下载并尝试使用该源代码。 新的下载包含原始源代码,以及一个带有更新源代码的小型 VS 项目。