Non-string values ​​in a DataGridViewComboBoxColumn causing DataErrors in a DataGridView

I have a programmatically populated DataGridView with some DataGridViewComboBoxColumn elements. These ComboBoxes contain custom types that have their ToString() overwritten to hide their guts from the user.

Problem: whenever I change the value of the ComboBox and select another cell, CellValidating is CellValidating , FormattedValue is the string result of my custom FooBar.ToString () (should be fine). In CellEndEdit , the ValueType value is a string, not my custom type, and I get an error either when viewing row.Cell-Member in VS, or when using the mouse in a modified cell (translated from German):

"DataGridView-Exception: System.ArgumentException : DataGridViewComboBoxCell -Value is not valid. Refer to DataError-Exception to replace this dialog box

This creates a column - colFoo - this is DataGridViewComboBoxColumn :

  dataGridInstance.Columns[1].CellTemplate.Value = new FooBar("bla", 31); dataGridInstance.Columns[1].CellTemplate.ValueType = typeof(FooBar); foreach (FooBar foo in FooBarArray) colSymbol.Items.Add(sym); 

The grid is filled as follows:

  foreach (FooLine line in SomeFooLineArray) { DataGridViewRow newRow = ((DataGridViewRow)dataGridInstance.RowTemplate.Clone()); newRow.Cells[1].Value = line.Foo; // FooBar instance field dataGridInstance.Rows.Add(newRow); } 

Any experiments in CellValidating or CellFormatting failed, I always get this message.

How to add custom types to an existing DataGridView without overwriting too much? Almost every other component (including dropboxes) supports custom types only in order, only the problem of copying values ​​from Combo to mesh seams is a problem.

As specified, the FooBar implementation is as follows:

  internal class FooBar { private readonly int id; private readonly string name; internal FooBar(string n, int i) { id = i; name = n; } public override string ToString() { return name; } } 

This is a bit more, but it is significant functionality encapsulated.

+4
source share
3 answers

You tried to change

 internal FooBar(string n, int i) { id = i; name = n; } to read like this internal FooBar(string n, int i) { this.id = i; this.name = n; } 
0
source

I know this is an old question, but I just ran into this problem and I hope the solution will be helpful.

First off, the DataGridViewComboBoxColumn works fine if you use rows. The idea of ​​having a ComboBox using objects is great (and just what I wanted), but if this is what you want, there are a few hurdles that you need to slip through (perhaps because the developers have forgotten).

The first is to set the ValueType column (which you do in your code), i.e.:

 dataGridInstance.Columns[1].CellTemplate.ValueType = typeof(FooBar); 

or you can set it directly in the column:

 dataGridInstance.Columns[1].ValueType = typeof(FooBar); 

The second bit (and this is what you are missing) is that you need a way to convert from a string back to an instance of your FooBar data class. You do this by providing a custom event for CellParsing , which should look something like this:

 private void dataGridInstance_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if (e.DesiredType == typeof(ListItem)) { if (e.Value != null) { DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridInstance.Rows[e.RowIndex].Cells[e.ColumnIndex]; foreach (object item in comboCell.Items) { if (item.ToString() == e.Value.ToString()) { e.Value = item; e.ParsingApplied = true; return; } } } } } 

What is it.

One of them: yes, if two objects have the same representation .ToString() , then this does not tell them separately (but this is a limitation inherent in the control). Therefore, if you can make sure that the string representation is unique.

0
source

Your columns must have the same data type.

Let them talk

TableForComboColumn id Int32 name Varchar

TableWithComboColumn

id Int32 TableForComboColumn_id Int16 -> this should also be Int32

0
source

Source: https://habr.com/ru/post/1389070/


All Articles