FormatException w/DataGridView when binding to a list of custom o

G

Guest

I am binding a DataGridView with a List of custom objects which itself has
both intrinsic and custom properties. I accomplish the binding through a
BindingSource instantiated with a BindingList instantiated with the list of
custom objects. The grid correctly sets up all of the columns, but does not
allow me to enter a new value for columns that represent custom properties of
the unterlying object. Intrinsic and string values do not have the same
problem.

The problem occurs after after entering a valid value it the problematic
column, attempting to move off the cell throws a FormatException with a
message that starts with "Invalid cast from 'System.String' to ..."

The offending object type is defined as a struct and implements a
IConvertible and several implicit operators including to and from string
casting.

Any help in the matter would be greatly appreciated.

Nejat
 
B

Bart Mermuys

Hi,

Nejat said:
I am binding a DataGridView with a List of custom objects which itself has
both intrinsic and custom properties. I accomplish the binding through a
BindingSource instantiated with a BindingList instantiated with the list
of
custom objects. The grid correctly sets up all of the columns, but does
not
allow me to enter a new value for columns that represent custom properties
of
the unterlying object. Intrinsic and string values do not have the same
problem.

The problem occurs after after entering a valid value it the problematic
column, attempting to move off the cell throws a FormatException with a
message that starts with "Invalid cast from 'System.String' to ..."

The offending object type is defined as a struct and implements a
IConvertible and several implicit operators including to and from string
casting.

Any help in the matter would be greatly appreciated.

Try implementing a TypeConverter instead or in addition:

[TypeConverter(typeof(SomeStructConverter))]
public struct SomeStruct
{
....
}

public class SomeStructConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type
destinationType)
{
return (destinationType == typeof(string));
}

public override bool CanConvertFrom(ITypeDescriptorContext context, Type
sourceType)
{
return (sourceType == typeof(string));
}

public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type
destinationType)
{
// convert from struct to string
SomeStruct st = (SomeStruct) value;
...
return ...
}

public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
// convert from string to struct
string s = (string) value;
...
return ...
}
}

Within the TypeConverter you could also use your struct operators or
IConvertible to do the conversion if you still planning on implementing
those too.


HTH,
Greetings
 
G

Guest

Bart you are the man, that did it. It also explains why the default cast
attempted by the binding source doesn't work. If the source worked with a
string value rather than an object value the attempted cast would have
worked, because of my implicit operator definition.

Thanks again, Nejat
 
B

Bart Mermuys

Hi,

Nejat said:
Bart you are the man, that did it. It also explains why the default cast
attempted by the binding source doesn't work. If the source worked with a
string value rather than an object value the attempted cast would have
worked, because of my implicit operator definition.

The error message is deceptive, it doesn't perform any casting.

It can't really cast to a type only known at runtime (DGVCell.ValueType vs
DGVCell.FormattedValueType), though it ain't impossible to find and use the
right user-defined operators using reflection.

But it only finds/uses a TypeConverter (System.ComponentModel). The
primitive types all have an associated TypeConverter which allow conversion
from and to string.

Greetings
Thanks again, Nejat

Bart Mermuys said:
Try implementing a TypeConverter instead or in addition:

[TypeConverter(typeof(SomeStructConverter))]
public struct SomeStruct
{
....
}

public class SomeStructConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type
destinationType)
{
return (destinationType == typeof(string));
}

public override bool CanConvertFrom(ITypeDescriptorContext context,
Type
sourceType)
{
return (sourceType == typeof(string));
}

public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type
destinationType)
{
// convert from struct to string
SomeStruct st = (SomeStruct) value;
...
return ...
}

public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
// convert from string to struct
string s = (string) value;
...
return ...
}
}

Within the TypeConverter you could also use your struct operators or
IConvertible to do the conversion if you still planning on implementing
those too.
 
G

Guest

Casting probably is not the correct term. Though I am not definite about it,
it must be doing some type of conversion; how else does it store other types?
For instance it handles int types without a problem.

Interestingly enough, when I use the convert utility class
(SomeStruct)Convert.ChangeType("Some Value", typeof(SomeStruct)) I get the
identical error message: Invalid cast from 'System.String' to
'mynamespace.SomeStruct'.

However I don't believe it uses this mechansim for the int example because
you can't convert to an int from a string.

Though the problem is solved, its good to understand why the problem occured
in the first place. Thanks again for your insight into my problem.
 
B

Bart Mermuys

Hi,

Nejat said:
Casting probably is not the correct term. Though I am not definite about
it,
it must be doing some type of conversion; how else does it store other
types?
For instance it handles int types without a problem.

Interestingly enough, when I use the convert utility class
(SomeStruct)Convert.ChangeType("Some Value", typeof(SomeStruct)) I get the
identical error message: Invalid cast from 'System.String' to
'mynamespace.SomeStruct'.

I guess Convert.ChangeType can't convert to SomeStruct, since IConvertable
doesn't contain a method that could be used.

<Quote from SDK doc>
Allows conversion from a custom type to other data types but not from other
data types to the custom type.
However I don't believe it uses this mechansim for the int example because
you can't convert to an int from a string.

It first finds/uses a TypeConverter, like i mentioned in my previous post,
each basic type has an associated TypeConverter, eg. :

TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(int));

Console.WriteLien( intConverter.GetType() ); // prints Int32Converter
Console.WriteLine( intConverter.CanConvertTo(typeof(string)); // prints true
Console.WriteLine( intConverter.CanConvertFrom(typeof(string)); // prints
true

But then after having a clooser look, it seems that when no TypeConverter
can be found on the target or source that can do the conversion, it will
check if the source implements IConvertable and in case of DGV->DataSource,
the source is a string that implements IConvertable, so it will try
Convert.ChangeType which will throw an InvalidCastException.

The InvalidCastException is catched and then used as the inner exception for
the FormatException that is thrown instead. So that's probely why the
errormessage is identical, good observation on your part.
Though the problem is solved, its good to understand why the problem
occured
in the first place.

Can't agree more though it's not always easy to get there.
Thanks again for your insight into my problem.

You're welcome.

HTH,
Greetings
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top