简体   繁体   English

绑定到DataTable的DataGridViewComboBoxColumn上的DataError

[英]DataError on DataGridViewComboBoxColumn bound to a DataTable

I've found several topics with a similar issue but the contents seemed slightly different and I have not been able to solve my problem as a result. 我发现了几个主题相似的问题,但是内容似乎略有不同,因此我无法解决问题。

In my application I have DataTable that contains 4 columns: 在我的应用程序中,我有包含4列的DataTable:

  • UInt16 UInt16
  • UInt64 UInt64
  • UInt64 UInt64
  • A self defined enumeration type consisting of 2 values. 自定义的枚举类型,由2个值组成。

In order to display the values of this DataTable I created a DataGridView and set this table as the datasource. 为了显示此DataTable的值,我创建了一个DataGridView并将此表设置为数据源。 So far so good. 到现在为止还挺好。 I wanted the enumeration field column to contain comboboxes instead and ran into the DataGridViewComboBoxColumn type. 我希望枚举字段列改为包含组合框,并遇到DataGridViewComboBoxColumn类型。 I had some issues getting it to work but eventualy ended up using the following approach: 我在使它工作时遇到了一些问题,但最终还是使用了以下方法:

// Create the 4 datarows

// Add the datarows to the data table

// Set the data table as the data source for the data grid view

// Remove the column that represents the enumeration

// Add a DataGridViewComboBoxColumn to the DataGridView as replacement

I have created the DataGridViewComboBoxColumn as follows: 我创建了DataGridViewComboBoxColumn,如下所示:

DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.HeaderText   = "My header text";
cb.ValueType    = typeof(MyEnumType);
cb.DataSource   = Enum.GetValues(typeof(MyEnumType));
cb.FlatStyle    = FlatStyle.System;
cb.Name         = "Name"; //Same name as the DataColumn and the now deleted DataGridViewColumn
cb.DataPropertyName = "Name"; //Same name as the DataColumn and the now deleted DataGridViewColumn
cb.DisplayStyle     = DataGridViewComboBoxDisplayStyle.Nothing;

dataGridView.Columns.Add(cb);

Once my application starts I read in data from a text file that get placed into a structure with fields of the 4 datatypes mentioned above. 一旦我的应用程序启动,我将从一个文本文件中读取数据,该文件被放入具有上述4种数据类型的字段的结构中。 I then add these fields to the DataTable as follows: 然后,将这些字段添加到DataTable中,如下所示:

DataRow row = dataTable.NewRow();
row["Name of the UInt16 column"]    = mystruct.theUInt16;
row["Name of the UInt64 column"]    = mystruct.theUInt64;
row["Name of the UInt64 column"]    = mystruct.theUInt64_2;
row["Name of the enum column"]      = mystruct.theEnumValue;               
dataTable.Rows.Add(row);

on startup the DataError event gets called repeatedly. 在启动时,将反复调用DataError事件。 The contents of the cells do get filled properly however. 但是,单元格的内容确实可以正确填充。 (I see this after clicking away the error a couple of times) Disabling the DataError event (assigning an empty handler for example) is something I prefer to not do. (我多次单击错误后就看到了这一点)我不喜欢禁用DataError事件(例如,分配一个空处理程序)。

I think there is some sort of type mismatch somehow. 我认为某种程度上类型不匹配。 (maybe the enum type and a string for display?) This is however only a guess. (也许是枚举类型和要显示的字符串吗?)但这只是一个猜测。 The dataTable column and the datagridview column both have the type set to the enumeration. dataTable列和datagridview列都将类型设置为枚举。

I hope someone can point me in the right direction. 我希望有人能指出我正确的方向。

Thanks in advance! 提前致谢!

Instead of adding and removing the last column, how about listening for the ColumnAdded event in the DataGridView then changing the type then: 与其添加和删除最后一列, ColumnAddedDataGridView侦听ColumnAdded事件,然后更改类型,然后:

dataGridView.ColumnAdded += DataGridViewColumnAdded;
dataGridView.DataSource = dataTable;

private void DataGridViewColumnAdded(Object sender, DataGridViewColumnEventArgs e) 
{
   if(e.Column.ValueType == typeof(MyEnumType)) 
   {
      DataGridViewComboBoxCell cb = new DataGridViewComboBoxCell();
      cb.ValueType        = typeof(MyEnumType);
      cb.DataSource       = Enum.GetValues(typeof(MyEnumType));
      cb.FlatStyle        = FlatStyle.System;
      cb.DisplayStyle     = DataGridViewComboBoxDisplayStyle.Nothing;
      e.Column.CellTemplate = cb;
   } 
}

I have managed to find a workaround that suits my needs. 我设法找到了适合我需要的解决方法。 The approach is still the same as in my original post. 方法仍然与我的原始帖子相同。 I made gave the enum in the DataTable the name "colMyEnumTypeTable" and the datatype is string instead of MyEnumType. 我为DataTable中的枚举指定了名称“ colMyEnumTypeTable”,并且数据类型是字符串而不是MyEnumType。 Then I removed this column and added the DataGridViewComboBoxColumn named "colMyEnumType" with DataPropertyName "colMyEnumTypeTable" and also being of type string. 然后,我删除了此列,并添加了名为“ colMyEnumType”的DataGridViewComboBoxColumn和DataPropertyName“ colMyEnumTypeTable”,并且其类型也是字符串。 I then convert the enumeration values to string when adding them to the data table, and when extracting I use Enum.Parse to retrieve the enum value again. 然后,在将枚举值添加到数据表中时以及在提取时,我将枚举值转换为字符串,然后使用Enum.Parse再次检索枚举值。 No more DataError calls are made. 不再进行DataError调用。

-edit- I gave the DataTable and DataGridViewComboBoxColumn different names to ensure that wasn't causing problems. -edit-我给DataTable和DataGridViewComboBoxColumn提供了不同的名称,以确保不会引起问题。 I have now changed them back so they have the same name and it still works. 我现在将它们改回了名称,因此它们仍然有效。

-edit2- And instead of setting the DataSource property for the comboboxcolumn I added the enum values by adding them to the Items property. -edit2-而不是为comboboxcolumn设置DataSource属性,而是通过将枚举值添加到Items属性中来添加枚举值。 (after converted to string) (转换为字符串后)

The reason why assigning the enum directly to the combo box with a datatable gives the 'value is not valid' error is the type difference between the enum in the DataGridViewComboBoxColumn and the integral value in the DataRow (Enums are always stored as their underlying type in a DataRow regardless if the column type is set to the enum type). 将枚举直接分配给具有数据表的组合框会导致“值无效”错误的原因是,DataGridViewComboBoxColumn中的枚举与DataRow中的整数值之间的类型不同(枚举始终存储为它们的基础类型DataRow(无论列类型是否设置为枚举类型)。 eg if you read back row["Name of the enum column"] after calling row["Name of the enum column"] = mystruct.theEnumValue; 例如,如果您在调用row["Name of the enum column"] = mystruct.theEnumValue; row["Name of the enum column"]之后读回row["Name of the enum column"] row["Name of the enum column"] = mystruct.theEnumValue;
it wouldn't be the enum you had just assigned but its underlying value. 它不是您刚刚分配的枚举,而是它的基础值。 This post: DataGridView linked to DataTable with Combobox column based on enum has an alternative solution using a Key-Value DataSource. 这篇文章: DataGridView通过基于枚举的Combobox列链接到DataTable,还有一个使用键值数据源的替代解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM