ICustomTypeDescriptor vs Remoting

R

Robert Ludig

I am using System.Windows.Forms.PropertyGrid to display the properties
of some custom objects. To enable dynamic modification of those
properties (and its attributes) this class hast to derive from
ICustomTypeDescriptor. Now I want those objects to be marshalled (by
reference) across process boundaries. So they can be viewed in a
propertygrid on a remote machine. Unfortunately ICustomTypeDescriptor
contains several types that are not serializable and not
marshalbyrefobjects. So types derived from ICustomTypeDescriptor can
never be serialized. Do you see any way how to support dynamic
properties in propertygrid AND being able to remote those objects ?
 
D

Dave Sexton

Hi Robert,

ICustomTypeDescriptor is not required. You can create a custom TypeConverter that will provide your object dynamic properties at
runtime to be used by a PropertyGrid: Derive a class from System.ComponentModel.PropertyDescriptor to encapsulate your 'dynamic'
properties.

Here's an example of a custom TypeConverter you can use for an object name CustomObject:

public class CustomObjectTypeConverter : ExpandableObjectConverter
// ExpandableObjectConverter allows and instance of an object to which the
// CustomObjectTypeConverter class is applied using the TypeConverterAttribute
// to be expandable in the PropertyGrid when used as the Type of a property
// for another class.
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;

return base.CanConvertTo (context, destinationType);
}

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type
destinationType)
{
if (context == null)
throw new ArgumentNullException("context");

if (value is CustomObject && destinationType == typeof(string))
// this is the string value displayed in the PropertyGrid for an expandable object (+)
return string.Format("[{0}]", context.PropertyDescriptor.DisplayName);

return base.ConvertTo (context, culture, value, destinationType);
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
if (context == null || !(context.Instance is CustomObject))
return base.GetPropertiesSupported(context);

return true;
}

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
CustomObject owner = value as CustomObject;

if (owner == null)
return base.GetProperties(context, value, attributes);

// return value declared here, filled in the foreach loop below
PropertyDescriptorCollection props = new PropertyDescriptorCollection(null);

// this line simply creates a collection of custom PropertyDescriptor objects
// for the owner (CustomObject).
CustomObjectDynamicProperties[] dynamicProps = owner.GetDynamicProperties();

foreach (PropertyDescriptor prop in dynamicProps)
{
// PropertyGrid doesn't check IsBrowsable for dynamic properties
// so you'll have to check that yourself:
if (prop != null && !prop.Attributes.Matches(new BrowsableAttribute(false)))
// Add the option
props.Add(prop);
}

return props;
}
}
 
R

Robert Ludig

MH, sorry , maybe I should have been more precise in the first place. I
not only want to be able to dynamically modify the properties of those
objects displayed in the property grid but also dynamically modify a
lot of other displayed texts in the propertygrid such as:
- the description displayed in the lower area of the propertygid
- the name of the property (displayed on the left side of each
property)
- modify the order in wich the properties are sorted in the
propertygrid
- change visibility and readonly state for properties at runtime

I dont see how that can be done without deriving from
ICustomTypeDescriptor. Do you see a way?

Dave said:
Hi Robert,

ICustomTypeDescriptor is not required. You can create a custom TypeConverter that will provide your object dynamic properties at
runtime to be used by a PropertyGrid: Derive a class from System.ComponentModel.PropertyDescriptor to encapsulate your 'dynamic'
properties.

Here's an example of a custom TypeConverter you can use for an object name CustomObject:

public class CustomObjectTypeConverter : ExpandableObjectConverter
// ExpandableObjectConverter allows and instance of an object to which the
// CustomObjectTypeConverter class is applied using the TypeConverterAttribute
// to be expandable in the PropertyGrid when used as the Type of a property
// for another class.
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;

return base.CanConvertTo (context, destinationType);
}

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type
destinationType)
{
if (context == null)
throw new ArgumentNullException("context");

if (value is CustomObject && destinationType == typeof(string))
// this is the string value displayed in the PropertyGrid for an expandable object (+)
return string.Format("[{0}]", context.PropertyDescriptor.DisplayName);

return base.ConvertTo (context, culture, value, destinationType);
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
if (context == null || !(context.Instance is CustomObject))
return base.GetPropertiesSupported(context);

return true;
}

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
CustomObject owner = value as CustomObject;

if (owner == null)
return base.GetProperties(context, value, attributes);

// return value declared here, filled in the foreach loop below
PropertyDescriptorCollection props = new PropertyDescriptorCollection(null);

// this line simply creates a collection of custom PropertyDescriptor objects
// for the owner (CustomObject).
CustomObjectDynamicProperties[] dynamicProps = owner.GetDynamicProperties();

foreach (PropertyDescriptor prop in dynamicProps)
{
// PropertyGrid doesn't check IsBrowsable for dynamic properties
// so you'll have to check that yourself:
if (prop != null && !prop.Attributes.Matches(new BrowsableAttribute(false)))
// Add the option
props.Add(prop);
}

return props;
}
}

--
Dave Sexton

Robert Ludig said:
I am using System.Windows.Forms.PropertyGrid to display the properties
of some custom objects. To enable dynamic modification of those
properties (and its attributes) this class hast to derive from
ICustomTypeDescriptor. Now I want those objects to be marshalled (by
reference) across process boundaries. So they can be viewed in a
propertygrid on a remote machine. Unfortunately ICustomTypeDescriptor
contains several types that are not serializable and not
marshalbyrefobjects. So types derived from ICustomTypeDescriptor can
never be serialized. Do you see any way how to support dynamic
properties in propertygrid AND being able to remote those objects ?
 
D

Dave Sexton

Hi Robert,

When you override the TypeConverter.GetProperties method you will return a list of custom PropertyDescriptor objects.
PropertyDescriptor encapsulates all of the information required by the PropertyGrid to display an item. You can add Attributes to
your custom PropertyDescriptor at runtime. This is different than adding Attributes to a real property at design-time because the
properties aren't defined in your class, however they are treated the same by the PropertyGrid at runtime. The grid doesn't care
where the Attributes came from as long as they appear on each PropertyDescriptor.

And by "Attributes" I'm referring to the PropertyGrid Attributes from the System.ComponentModel namespace such as
BrowsableAttribute, DisplayNameAttribute, ReadOnlyAttribute and DescriptionAttribute. Each of these Attributes can be used to
handle the functionality that you require, stated in your previous post. Just add them to the Attributes collection of each of your
custom PropertyDescriptor instances, where you require them, before returning from the GetProperties method. The PropertyGrid will
read them as if you declared them at design-time on a real property.

About sorting, I'm not sure you'll have much control over that. I haven't played around with anything new to the PropertyGrid in
2.0 so I'm not sure if they added any control over sorting but I couldn't do it in the 1.* frameworks. GL.

--
Dave Sexton

Robert Ludig said:
MH, sorry , maybe I should have been more precise in the first place. I
not only want to be able to dynamically modify the properties of those
objects displayed in the property grid but also dynamically modify a
lot of other displayed texts in the propertygrid such as:
- the description displayed in the lower area of the propertygid
- the name of the property (displayed on the left side of each
property)
- modify the order in wich the properties are sorted in the
propertygrid
- change visibility and readonly state for properties at runtime

I dont see how that can be done without deriving from
ICustomTypeDescriptor. Do you see a way?

Dave said:
Hi Robert,

ICustomTypeDescriptor is not required. You can create a custom TypeConverter that will provide your object dynamic properties at
runtime to be used by a PropertyGrid: Derive a class from System.ComponentModel.PropertyDescriptor to encapsulate your
'dynamic'
properties.

Here's an example of a custom TypeConverter you can use for an object name CustomObject:

public class CustomObjectTypeConverter : ExpandableObjectConverter
// ExpandableObjectConverter allows and instance of an object to which the
// CustomObjectTypeConverter class is applied using the TypeConverterAttribute
// to be expandable in the PropertyGrid when used as the Type of a property
// for another class.
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;

return base.CanConvertTo (context, destinationType);
}

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type
destinationType)
{
if (context == null)
throw new ArgumentNullException("context");

if (value is CustomObject && destinationType == typeof(string))
// this is the string value displayed in the PropertyGrid for an expandable object (+)
return string.Format("[{0}]", context.PropertyDescriptor.DisplayName);

return base.ConvertTo (context, culture, value, destinationType);
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
if (context == null || !(context.Instance is CustomObject))
return base.GetPropertiesSupported(context);

return true;
}

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[]
attributes)
{
CustomObject owner = value as CustomObject;

if (owner == null)
return base.GetProperties(context, value, attributes);

// return value declared here, filled in the foreach loop below
PropertyDescriptorCollection props = new PropertyDescriptorCollection(null);

// this line simply creates a collection of custom PropertyDescriptor objects
// for the owner (CustomObject).
CustomObjectDynamicProperties[] dynamicProps = owner.GetDynamicProperties();

foreach (PropertyDescriptor prop in dynamicProps)
{
// PropertyGrid doesn't check IsBrowsable for dynamic properties
// so you'll have to check that yourself:
if (prop != null && !prop.Attributes.Matches(new BrowsableAttribute(false)))
// Add the option
props.Add(prop);
}

return props;
}
}

--
Dave Sexton

Robert Ludig said:
I am using System.Windows.Forms.PropertyGrid to display the properties
of some custom objects. To enable dynamic modification of those
properties (and its attributes) this class hast to derive from
ICustomTypeDescriptor. Now I want those objects to be marshalled (by
reference) across process boundaries. So they can be viewed in a
propertygrid on a remote machine. Unfortunately ICustomTypeDescriptor
contains several types that are not serializable and not
marshalbyrefobjects. So types derived from ICustomTypeDescriptor can
never be serialized. Do you see any way how to support dynamic
properties in propertygrid AND being able to remote those objects ?
 

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