使用ComboBox将DataGridView绑定到DataTable不起作用 [英] Binding DataGridView to DataTable with ComboBox not working

查看:50
本文介绍了使用ComboBox将DataGridView绑定到DataTable不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建绑定到DataTable的DataGridView,其中一列是ComboBox.该代码运行,但绑定后(而不是绑定数据时)出现以下错误:System.ArgumentException:DataGridViewComboBoxCell值无效.

在DataGridView中,其中一列是DataGridViewComboBoxColumn,它使用枚举(命名为structureType)作为源:

 //ColumnStructure//this.ColumnStructure.ValueType = typeof(structureType);this.ColumnStructure.DataSource =枚举GetValues(typeof(structureType));this.ColumnStructure.HeaderText =结构";this.ColumnStructure.Name ="ColumnStructure";this.ColumnStructure.DataPropertyName =结构";// 

当我不使用DataTable填充DataGridView时,它就可以正常工作:

  structureType?结构= GetStructure(部分);dgvObjectTypes.Rows.Add(名称,类型,结构,计数); 

现在,我想改用DataTable,但无法使其正常工作.DataTable的创建如下:

  DataTable表= new DataTable();table.Columns.Add("Name",typeof(string));table.Columns.Add("Type",typeof(string));table.Columns.Add("Structure",typeof(DataGridViewComboBoxCell));table.Columns.Add("Count",typeof(int)); 

其他列效果很好,但我无法使"Structure"列正常工作.这是我尝试创建组合框的方法:

  var cb = new DataGridViewComboBoxCell();cb.ValueType = typeof(structureType);cb.DataSource = Enum.GetValues(typeof(structureType));cb.Value =(structureType)结构; 

之后,我只为表创建行,并将表设置为DataGridView的数据源:

  table.Rows.Add(name,type,cb,count);dgv.DataSource = table; 

我读过很多帖子,其中指出在组合框中使用枚举会引起问题(例如:

I'm trying to create a DataGridView bound to a DataTable where one column is a ComboBox. The code runs but I get the following error after binding (not when data is bound): System.ArgumentException: DataGridViewComboBoxCell value is not valid.

In the DataGridView one of the columns is a DataGridViewComboBoxColumn that uses an enum (named structureType) as it's source:

// ColumnStructure
// 
this.ColumnStructure.ValueType = typeof(structureType);
this.ColumnStructure.DataSource = Enum.GetValues(typeof(structureType));
this.ColumnStructure.HeaderText = "Structure";
this.ColumnStructure.Name = "ColumnStructure";
this.ColumnStructure.DataPropertyName = "Structure";
//

When I populate the DataGridView without using a DataTable, it works just fine:

structureType? structure = GetStructure(part);
dgvObjectTypes.Rows.Add(name, type, structure, count);

Now I would want to use a DataTable instead, but can't get it to work. The DataTable is created as follows:

DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Type", typeof(string));
table.Columns.Add("Structure", typeof(DataGridViewComboBoxCell));
table.Columns.Add("Count", typeof(int));

Other columns work great but I can't get the "Structure" column to work. Here's how I've tried to create the combobox:

var cb = new DataGridViewComboBoxCell();
cb.ValueType = typeof(structureType);
cb.DataSource = Enum.GetValues(typeof(structureType));
cb.Value = (structureType)structure;

After that I just create the rows for the table and and set the table as datasource for the DataGridView:

table.Rows.Add(name, type, cb, count);
dgv.DataSource = table;

I've read a lot of posts where it has been stated that using enums in comboboxes causes problems (this for example: DataGridView linked to DataTable with Combobox column based on enum), but that doesn't seem to be the case here. I even tried to use explicitly typed arrays of strings but still get the same error. I think I'm doing something wrong with the DataGridViewComboBoxCell.

What could be the problem?

解决方案

It seems like the step you are missing is providing the Names and Values for the CBO. The DataTable can store the value, and the DGV can display the related name, but you need to help provide the translation.

private enum structureType
{ None, Circle, Square, Pyramid}
...

dtStruct = new DataTable();
dtStruct.Columns.Add("Name", typeof(string));
dtStruct.Columns.Add("Type", typeof(string));
dtStruct.Columns.Add("Structure", typeof(structureType));
dtStruct.Columns.Add("Count", typeof(int));

// autogen columns == true
dgv2.DataSource = dtStruct;

// create DataSource as list of Name-Value pairs from enum
var cboSrc = Enum.GetNames(typeof(structureType)).
                    Select( x => new {Name = x, 
                                      Value = (int)Enum.Parse(typeof(structureType),x)
                                      }
                           ).ToList();

// replace auto Text col with CBO col
DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.ValueType = typeof(structureType);
cb.DataSource = cboSrc;
cb.DisplayMember = "Name";          // important
cb.ValueMember = "Value";           // important
cb.HeaderText = "Structure";
cb.DataPropertyName = "Structure";  // where to store the value

dgv2.Columns.Remove(dgv2.Columns[2]);  // remove txt col
dgv2.Columns.Add(cb);
cb.DisplayIndex = 2;

// add data
dtStruct.Rows.Add("Ziggy", "Foo", structureType.Circle, 6);

The first part creates the DataTable, note that the Structure column type is structureType (or often int). The DataTable will be storing data, not DataGridViewComboBoxCell elements. In cases where the data comes from a database, that column would be int since structureType would not be a known type.

A DataSource is then created from the enum names and values. This provides the means for the control to show the name, yet store the value in the DataTable.

If the DGV is set to auto generate columns, you will need to replace the default TextBoxColumn with a ComboBoxColumn. This is being done after the DataSource has been set, but before any data is added. When the data comes from a DB (and so there is not usually an empty, typed table) you can use the ColumnAdded event to swap out one column for another.

The important thing when adding the CBO column is to set the ValueMember and DsiplayMember properties to provide the Value <-> Name translation and DataPropertyName so it knows where to store the selected value in the DataTable.

这篇关于使用ComboBox将DataGridView绑定到DataTable不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆