Using WinForms, I'm trying to write a method that checks if the data item bound to a row in a DataGridView contains an IList
as a property and then automatically transforms the DataGridViewTextBoxCell
into a DataGridViewComboBoxCell
binding that list as a datasource. The objective is to have a dropdown menu with different values for each row depending on the elements in the list property of the object found. So for example in the first row the dropdown could have 3 objects of type ObjA
as options, the second row could have 5 objects of type ObjC
, and so on.
This is what I have:
private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow row in dgv.Rows)
{
object obj = row.DataBoundItem;
if (obj != null)
{
IEnumerable listProperties = obj.GetType().GetProperties().Where(p => p.GetValue(obj) is IList);
foreach (PropertyInfo list in listProperties)
{
DataGridViewComboBoxCell cell = new DataGridViewComboBoxCell();
IList source = (IList)list.GetValue(obj, null);
cell.DataSource = source;
cell.ValueMember = "id";
cell.DisplayMember = "name";
cell.ValueType = source.GetType().GetProperty("Item").PropertyType;
cell.Value = source[0].GetType().GetProperty("id").GetValue(source[0]);
(row.Cells[list.Name]) = cell;
}
}
}
}
And this is the code that binds the initial data to the DataGridView
:
IBindingList source = new BindingList<Models.InputValue>(datasource);
inputsDgv.AutoGenerateColumns = true;
inputsDgv.AllowUserToAddRows = false;
inputsDgv.AllowUserToDeleteRows = false;
inputsDgv.DataSource = source;
Problem: I'm getting a "DataGridViewComboBoxCell value is not valid" error when loading the DataGridView. I noticed that after running the line (row.Cells[list.Name]) = cell;
, the cell.ValueType
changes from System.Collections.Generic.IList1[[roco.Models.ISnapshots]]
to System.Int32
. I figured that must the the problem.
Does any one know how I can go around this error?
Thanks!
P.S.: The row.DataBoundItem
is of type InputValue
and the list property is a collection of ProjectionSnapshot
objects
public class InputValue : IValues
{
private int _id;
public int id { get { return _id; } }
private IList<ISnapshots> _snapshots;
public IList<ISnapshots> snapshots
{
get { return _snapshots; }
set { _snapshots = value; }
}
}
public class ProjectionSnapshot : ISnapshots
{
private int _id;
public int id { get { return _id; } }
private string _name;
public string name
{
get { return _name; }
set
{
if (value.Length > 255)
Console.WriteLine("Error! SKU snapshot name must be less than 256 characters!");
else
_name = value;
}
}
}
public interface ISnapshots
{
int id { get; }
string name { get; set; }
}