In the previous post I gave an introduction on common TypeConverters and how to use them, in this post I will show you how to implement custom TypeConverters for your own custom data types.
First, lets explore the TypeConverter base type virtual methods …
Method | Description |
---|---|
CanConvertFrom | Returns a Boolean value indicating whether the converter can convert an object of the specified type to the type that this converter represents. |
CanConvertTo | Returns a Boolean value indicating whether the converter can convert an object to the specified type. |
ConvertFrom | Converts the specified value to the type represented by this converter. |
ConvertFromInvariantString | Converts the string representation of a value to a type that this converter represents, using the invariant culture, which is English. |
ConvertFromString | Converts the string representation of a value to a type that this converter represents, using the given culture. |
ConvertTo | Converts the given object to the specified type. |
ConvertToInvariantString | Converts the given object to a string, using the invariant culture. |
ConvertToString | Converts the given object to a string, using the specified culture. |
CreateInstance | Creates or recreates an object given a dictionary of property values. The dictionary contains property name-value pairs. |
GetCreateInstanceSupported | Returns a Boolean value indicating whether CreateInstance has been implemented. |
GetProperties | Returns a collection of PropertyDescriptor objects for the given object. |
GetPropertiesSupported | Returns a Boolean value indicating whether the given object supports properties. |
GetStandardValues | Returns a collection of standard values for the type that this converter represents. |
GetStandardValuesExclusive | Returns a Boolean value indicating whether the standard values are mutually exclusive. |
GetStandardValuesSupported | Returns a Boolean value indicating whether GetStandardValues is implemented. |
IsValid | Returns a Boolean value indicating whether the specified value is valid for the type that this converter represents. |
[more]
Now lets implement a simple one, considering a type Point3D which simply has 3 int properties representing a point in the 3D (x,y,z).
[code:c#]
public struct Point3D
{
private int _x;
private int _y;
private int _z;
public int X { get { return _x; } set { _x = value; } }
public int Y { get { return _y; } set { _y = value; } }
public int Z { get { return _z; } set { _z = value; } }
}
[/code]
When adding a Point3D property to our testing ButtonEx Control the Point would look like this in the PropertyWindow
[code:c#]
public class Point3DConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(Point3D))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object src, Type destinationType)
{
//convert to a string
if (destinationType == typeof(string))
{
Point3D p3 = (Point3D)src;
string result = p3.X + "," + p3.Y + "," + p3.Z;
return result;
}
return base.ConvertTo(context, culture, src, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object src) {
{
//convert from a string
if (src is string)
{
Point3D p3 = new Point3D();
string[] temp = ((string)src).Split(',');
p3.X = int.Parse(temp[0]);
p3.Y = int.Parse(temp[1]);
p3.Z = int.Parse(temp[2]);
return p3;
}
return base.ConvertFrom(context, culture, src);
}
}
[/code]
Now apply the Point3DConverter to the Point3D struct, so anytime the Point3D is used then the Point3DConverter is used by default as when you use the Size type it is always associated with the SizeConverter, same to FontConverter used default with Font type.
[code:c#]
[TypeConverter(typeof(Point3DConverter))]
public struct Point3D
[/code]
After applying the Converter the property would look like this:
This would be enough to use the Point3D smoothly in the desing time, but we can make it more fancy by overriding GetPropertiesSupported and GetProperties methods.
[code:c#]
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object src, Attribute[] attributes)
{
return TypeDescriptor.GetProperties(src, attributes);
}
[/code]
Now it will be expanded in the PropertyWindow
To show how the GetStandardValuesSupported and GetStandardValues work take a look on the following properties.
As you are expecting the values appearing in the drop down list are the StandardValues, accordingly the EnumConverter overrides those two methods in order to return the values of the Enum.
Next part I will show how to use the StandardValues and the rest of the methods.
Leave a Reply