65.9K
CodeProject 正在变化。 阅读更多。
Home

DataGrid 中的 ComboBox

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.38/5 (37投票s)

2004年6月5日

CPOL

3分钟阅读

viewsIcon

491008

downloadIcon

6638

如何在 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[],并具有两个名为 NameGUID 的属性。

其他示例期望 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 的想法。

如何使用

遗憾的是,我不知道如何使用 GridColumnStyles“注册”我的 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 已经解决了 DataGridComboBox 的问题,仍然有人下载并尝试使用该源代码。 新的下载包含原始源代码,以及一个带有更新源代码的小型 VS 项目。

© . All rights reserved.