How to bind a DataGridViewComboBoxColumn object to an object?

I am trying to bind a DataGridViewComboBoxColumn to an instance of Foo, but when I set the value in the grid, I got an ArgumentException telling me that I cannot convert from String to Foo.

 var data = (from item in someTable select new { Foo = item.foo, Bar = item.Bar }).ToList(); grid.DataSource = data; column.DataPropertyName = "Foo"; column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance 

Am I missing something? Is it possible to bind a binding to a complex object?

UPDATE:

I implemented TypeConverter and redefined CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Now i get

FormatException: DataGridViewComboBoxCell value is invalid

Any ideas?

+4
source share
4 answers

You are missing a possible fragment.

 column.DataPropertyName = "Foo"; column.DisplayMember = "SomeNameField"; column.ValueMember = "Bar"; // must do this, empty string causes it to be // of type string, basically the display value // probably a bug in .NET column.DataSource = from foo in Foo select foo; grid.DataSource = data; 

UPDATE:

Actually, after re-looking at your question, I think you encountered this marked error. Unfortunately, there is no way to force an object to return an object without using a custom TypeDescriptor / TypeConverter / BindingSource.

The answer is for binding to a complex object. By default, no. I wrote pretty good for my current project. This includes creating a custom TypeDescriptor / TypeConverter / BindingSource that returns all nested properties. Another "error" that you cannot use ". For the element separator I had to resort to": ".

+6
source

DataGridViewComboBoxColumn should always have all possible values โ€‹โ€‹in the list of combobox items or it will throw "FormatException: DataGridViewComboBoxCell value is not valid".

If you are trying to return values โ€‹โ€‹selected from a single combobox column, you can handle the CellParsing DataGridView event and get the selected item from DataGridView.EditingControl, because it will be set to edit the control from the edited column. Here is an example:

 private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if (dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn) { DataGridViewComboBoxEditingControl editingControl = (DataGridViewComboBoxEditingControl)dataGridView1.EditingControl; e.Value = editingControl.SelectedItem; e.ParsingApplied = true; } } 

You can also configure the way objects are displayed in each cell by handling the cell formatting event, here is the code that displays toString for any object or interface.

 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (e.Value != null) { e.Value = e.Value.ToString(); e.FormattingApplied = true; } } 

The processing of these two events should be sufficient to display and edit data in any business object and its lighter, and then a record type converter. For this to work, set the DataGridView and the combobox column as follows:

 var data = (from item in someTable select new { Foo = item.foo, Bar = item.Bar }).ToList(); grid.DataSource = data; column.DataPropertyName = "Foo"; column.DataSource = (from foo in Foo select foo).ToList (); 

No need to set the DisplayMember or ValueMember property, just make sure that the combobox list of data sources has all the possible values โ€‹โ€‹for Foo.

Hope this helps.

+6
source

In fact, you can use a complex type in a DataGridViewComboBoxColumn .

For instance:

 DataGridViewComboBoxColumn.DataPropertyName = "ValueMode"; DataGridViewComboBoxColumn.DisplayMember = "Label"; DataGridViewComboBoxColumn.ValueMember = "Self"; * DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem); 

Self is:

 public ValueModeItem Self { get { return this; } } 

Very important - you must override the Equals method of a complex type. In my case:

 public override bool Equals(object obj) { if (obj is ValueModeItem && obj != null) { if (...) return true; } return false; } 
+4
source

I constantly ran into the same problem until I found that you cannot set DisplayMember in a DataGridViewComboBoxCell without setting ValueMember .
Similarly, setting ValueMember , and not DisplayMember also crashes, you must define neither one nor the other.

Your model is Foo, and of course you want the ComboBox value to be the element itself. The easiest way to do this is to create a Property in your foo, returning itself.

 public class Foo { ... public Foo This { get {return this; } } } 

Then the bindings become:

 column.DataPropertyName = "Foo"; column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance column.ValueMember = "This"; 

This should work, and the cell value should be of type Foo, as expected.

Interesting link: Problems with DataGridViewComboBoxColumn

However, the DataGridViewComboBoxColumn is not working, although it will display a ToString value, if you do not set DisplayMember, something goes wrong internally when you try to select SelectedItem, you must set the DisplayMember to public property of your class. Even worse, the default behavior, if you do not set the ValueMember property to return DisplayMember, there is no way to get the actual item. The only work around is to add a property for your class that returns itself and sets this property to ValueMember. Of course, if your product is not something that you can change (for example, one of the framework classes), you will have to along with a container object that contains a link to your item.

+2
source

All Articles