Data binding Custom Object IList with descendant objects in the list
I am trying to data bind a IList of objects to the grid's drowdownlist. This list contains objects that descend from one another. For example, it might contain objects of Class1 and Class2, where Class2 inherits directly from Class1.
The drop down list appears correctly in the grid for all the objects in the list. However, if i select an item in the list that is of type Class2, I get an InvalidCastException - Object must implement IConvertible.
This is happening when the value is being set on the underlying record - there is a call to NullableHelper.ChangeType which calls Convert.ChangeType:
Syncfusion.ComponentModel.NullableHelper:
public static object ChangeType(object value, Type type)
{
return Convert.ChangeType(value, type);
}
The type that is passed in is from the Column's field descriptor which is of type Class1.
Isn't this call really only necessary if the passed in value is a ValueType? ie, int, decimal, float, etc.?
Can the grid's dropdown list be modified to support selection of descendant objects?
Regards,
Minh Tran
The drop down list appears correctly in the grid for all the objects in the list. However, if i select an item in the list that is of type Class2, I get an InvalidCastException - Object must implement IConvertible.
This is happening when the value is being set on the underlying record - there is a call to NullableHelper.ChangeType which calls Convert.ChangeType:
Syncfusion.ComponentModel.NullableHelper:
public static object ChangeType(object value, Type type)
{
return Convert.ChangeType(value, type);
}
The type that is passed in is from the Column's field descriptor which is of type Class1.
Isn't this call really only necessary if the passed in value is a ValueType? ie, int, decimal, float, etc.?
Can the grid's dropdown list be modified to support selection of descendant objects?
Regards,
Minh Tran
SIGN IN To post a reply.
6 Replies
AD
Administrator
Syncfusion Team
January 9, 2007 06:57 AM UTC
Hi Minh,
Please try the attached sample and let me know if you are trying something different.
GDBGDropDownCollections.zip
Best Regards,
Haneef
Please try the attached sample and let me know if you are trying something different.
GDBGDropDownCollections.zip
Best Regards,
Haneef
MT
Minh Tran
January 9, 2007 05:45 PM UTC
Hi Haneef,
No that is not what I'm trying to do. I've attached a demo Visual Studio 2003 project.
Essentially, I am binding custom objects - not datasets / datatables to the GridGroupingControl. One of the columns I've mapped - the Customer column draws from a datasource that has both Customer & GoodCustomer(GoodCustomer descends from Customer) objects in the IList. When you click on the Customer column drop down list in the grid you'll see 4 potential customers. The first 2 are Customer objects. The second 2 are GoodCustomer objects. If you pick the first 2, the grid has no problem setting the underlying record's value with your pick. If you pick one of the second 2, and then navigate off the column, you'll see a red exclamation mark next to the column showing an Inconvertible exception.
Syncfusion Version 4.111.0.50
Thanks,
Minh Tran
CustomObjectDataBinding.zip
No that is not what I'm trying to do. I've attached a demo Visual Studio 2003 project.
Essentially, I am binding custom objects - not datasets / datatables to the GridGroupingControl. One of the columns I've mapped - the Customer column draws from a datasource that has both Customer & GoodCustomer(GoodCustomer descends from Customer) objects in the IList. When you click on the Customer column drop down list in the grid you'll see 4 potential customers. The first 2 are Customer objects. The second 2 are GoodCustomer objects. If you pick the first 2, the grid has no problem setting the underlying record's value with your pick. If you pick one of the second 2, and then navigate off the column, you'll see a red exclamation mark next to the column showing an Inconvertible exception.
Syncfusion Version 4.111.0.50
Thanks,
Minh Tran
CustomObjectDataBinding.zip
AD
Administrator
Syncfusion Team
January 10, 2007 10:10 AM UTC
Hi Minh,
Thanks for your sample.
You should implement the ICovertible interface for coverting the GoodCustomer to Customer. Please refer to the attached sample for implementation and let me know if this helps.
Sample : ModifiedCustomObjectDataBinding.zip
Best Regards,
Haneef
public class Customer:IConvertible
{
public Customer(){}
public Customer(int id, string first, string last) {
this.id = id;
this.first = first;
this.last = last;
}
private int id;
public int ID
{
get {return id;}
set {id = value;}
}
private string first;
public string First
{
get {return first;}
set {first = value;}
}
private string last;
public string Last
{
get {return last;}
set {last = value;}
}
public string FullName
{
get {return first + " " + last;}
}
#region RequiredIConvertible Members
public string ToString(IFormatProvider provider)
{return this.FullName; }
public object ToType(Type conversionType, IFormatProvider provider)
{
if( conversionType == typeof(GoodCustomer))
return new GoodCustomer(this.ID,this.First,this.Last);
return null;
}
#endregion
#region DefaultIConvertible Members
///Default ICovertible member source code here.
#endregion
}
Thanks for your sample.
You should implement the ICovertible interface for coverting the GoodCustomer to Customer. Please refer to the attached sample for implementation and let me know if this helps.
Sample : ModifiedCustomObjectDataBinding.zip
Best Regards,
Haneef
public class Customer:IConvertible
{
public Customer(){}
public Customer(int id, string first, string last) {
this.id = id;
this.first = first;
this.last = last;
}
private int id;
public int ID
{
get {return id;}
set {id = value;}
}
private string first;
public string First
{
get {return first;}
set {first = value;}
}
private string last;
public string Last
{
get {return last;}
set {last = value;}
}
public string FullName
{
get {return first + " " + last;}
}
#region RequiredIConvertible Members
public string ToString(IFormatProvider provider)
{return this.FullName; }
public object ToType(Type conversionType, IFormatProvider provider)
{
if( conversionType == typeof(GoodCustomer))
return new GoodCustomer(this.ID,this.First,this.Last);
return null;
}
#endregion
#region DefaultIConvertible Members
///Default ICovertible member source code here.
#endregion
}
MT
Minh Tran
January 10, 2007 04:10 PM UTC
Hi Haneef,
The sample I gave you is something i just wrote up quickly to demonstrate the issue.
I do not have control of the object hierarchy in the business domain - they come from a different team of developers I work with.
My question is why is it necessary for Syncfusion to call Convert.ChangeType when setting the underlying record's value for a reference type? It doesn't make sense that I have to convert an object that descends from another object to a type that is it's parent.
If a cell's value is bound to an object that is of Type1. And another object is selected that is Type2(which descends from Type1), why shouldn't this be allowed without converting Type2 to Type1?
That's the whole point of OOP inheritance.
Regards,
Minh Tran
The sample I gave you is something i just wrote up quickly to demonstrate the issue.
I do not have control of the object hierarchy in the business domain - they come from a different team of developers I work with.
My question is why is it necessary for Syncfusion to call Convert.ChangeType when setting the underlying record's value for a reference type? It doesn't make sense that I have to convert an object that descends from another object to a type that is it's parent.
If a cell's value is bound to an object that is of Type1. And another object is selected that is Type2(which descends from Type1), why shouldn't this be allowed without converting Type2 to Type1?
That's the whole point of OOP inheritance.
Regards,
Minh Tran
TG
Tod Golding
May 30, 2007 08:48 PM UTC
This appears to be similar to a problem I'm having. I cannot appear to bind columns to custom data objects without requiring those objects to implement IConvertible. I'd been trying this with my own custom cell type and assumed it was just something I was doing wrong. Now I'm just trying to use a vanilla autocomplete combobox cell and I'm running into the same problem. My combo is populated with objects of "MyCustomType" and the column is bound to a columns with type of "MyCustomType" and I'm getting the "must implement IConvertible" error.
Can some please clarify what *is* and *is not* required when binding columns to custom data objects? I cannot use this control if it is going to impose requirements on my business objects. Please tell me there's something I'm overlooking.
>Hi Haneef,
The sample I gave you is something i just wrote up quickly to demonstrate the issue.
I do not have control of the object hierarchy in the business domain - they come from a different team of developers I work with.
My question is why is it necessary for Syncfusion to call Convert.ChangeType when setting the underlying record's value for a reference type? It doesn't make sense that I have to convert an object that descends from another object to a type that is it's parent.
If a cell's value is bound to an object that is of Type1. And another object is selected that is Type2(which descends from Type1), why shouldn't this be allowed without converting Type2 to Type1?
That's the whole point of OOP inheritance.
Regards,
Minh Tran
Can some please clarify what *is* and *is not* required when binding columns to custom data objects? I cannot use this control if it is going to impose requirements on my business objects. Please tell me there's something I'm overlooking.
>Hi Haneef,
The sample I gave you is something i just wrote up quickly to demonstrate the issue.
I do not have control of the object hierarchy in the business domain - they come from a different team of developers I work with.
My question is why is it necessary for Syncfusion to call Convert.ChangeType when setting the underlying record's value for a reference type? It doesn't make sense that I have to convert an object that descends from another object to a type that is it's parent.
If a cell's value is bound to an object that is of Type1. And another object is selected that is Type2(which descends from Type1), why shouldn't this be allowed without converting Type2 to Type1?
That's the whole point of OOP inheritance.
Regards,
Minh Tran
HA
haneefm
Syncfusion Team
May 30, 2007 11:10 PM UTC
Hi Tod,
One way you can avoid this problem by deriving the GridComboBoxCellRenderer class and override the OnSaveChanges method. Here is a code snippet to show this.
public class MyComboBoxCellModel : GridComboBoxCellModel
{
public MyComboBoxCellModel(GridModel grid): base(grid)
{ }
public override GridCellRendererBase CreateRenderer(GridControlBase control)
{
return new MyComboBoxCellRenderer(control, this);
}
}
public class MyComboBoxCellRenderer : GridComboBoxCellRenderer
{
public MyComboBoxCellRenderer(GridControlBase grid, GridCellModelBase cellModel) : base(grid, cellModel)
{ this.SupportsFocusControl = false; }
protected override bool OnSaveChanges()
{
Type type = this.Grid.Model[this.RowIndex,this.ColIndex].CellValue.GetType();
if (type == this.ControlValue.GetType())
return base.OnSaveChanges();
else
{
Customer cust = new Customer();
cust.ID = (this.ControlValue as GoodCustomer).ID;
cust.First = (this.ControlValue as GoodCustomer).First;
cust.Last = (this.ControlValue as GoodCustomer).Last;
this.Grid.Model[this.RowIndex, this.ColIndex].CellValue = cust;
}
return true;
}
}
Here is a modified sample.
http://websamples.syncfusion.com/samples/Grid.Windows/F61685/main.htm
Best regards,
Haneef
One way you can avoid this problem by deriving the GridComboBoxCellRenderer class and override the OnSaveChanges method. Here is a code snippet to show this.
public class MyComboBoxCellModel : GridComboBoxCellModel
{
public MyComboBoxCellModel(GridModel grid): base(grid)
{ }
public override GridCellRendererBase CreateRenderer(GridControlBase control)
{
return new MyComboBoxCellRenderer(control, this);
}
}
public class MyComboBoxCellRenderer : GridComboBoxCellRenderer
{
public MyComboBoxCellRenderer(GridControlBase grid, GridCellModelBase cellModel) : base(grid, cellModel)
{ this.SupportsFocusControl = false; }
protected override bool OnSaveChanges()
{
Type type = this.Grid.Model[this.RowIndex,this.ColIndex].CellValue.GetType();
if (type == this.ControlValue.GetType())
return base.OnSaveChanges();
else
{
Customer cust = new Customer();
cust.ID = (this.ControlValue as GoodCustomer).ID;
cust.First = (this.ControlValue as GoodCustomer).First;
cust.Last = (this.ControlValue as GoodCustomer).Last;
this.Grid.Model[this.RowIndex, this.ColIndex].CellValue = cust;
}
return true;
}
}
Here is a modified sample.
http://websamples.syncfusion.com/samples/Grid.Windows/F61685/main.htm
Best regards,
Haneef
SIGN IN To post a reply.
- 6 Replies
- 4 Participants
-
MT Minh Tran
- Jan 8, 2007 08:27 PM UTC
- May 30, 2007 11:10 PM UTC