User Control with a UITypeEditor of type IList<Control> throws exception "Control is not marked as serializable"

297 views Asked by At

I'm trying to add a property to my User Control of type IList<Control>, and I've implemented a UITypeEditor to show the user a CheckedListBox of controls from the form and allow the user to identify which controls to include. This works fine so far.

But when I try to close the UITypeEditor, the Designer shows a message "Property value is not valid" with the following details:

Type 'System.Windows.Forms.Control' in Assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

I'm not sure whether this would be solved by a TypeConverter, but if it is I'm not sure what the TypeConverter should return from the ConvertTo method (since you can't initialize a List from a constructor, and it would want references to the controls which I'm not sure how to pass back).

If necessary, I could change the type to Control[] if that would solve the problem with initializing from a constructor.

EDIT: I tried this TypeConverter, but despite associating it with the property on the User Control it doesn't seem to be used in any way.

class ControlListConverter : TypeConverter {
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
    if (destinationType == typeof(InstanceDescriptor)) return true;

    return base.CanConvertTo(context, destinationType);
}

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) {
    if (destinationType == typeof(InstanceDescriptor) && value is IList<Control>) {
        IList<Control> list = (IList<Control>)value;

        ConstructorInfo ctor = typeof(List<Control>).GetConstructor(new Type[] {typeof(IEnumerable<Control>)});

        if (ctor != null) {
            return new InstanceDescriptor(ctor, new object[] { list });
        }
    }

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

}

1

There are 1 answers

0
Jordy Boom On

The workaround solution to this that seems to work relatively well is to change the property to an IList and store the control names instead. Then when you need to access the controls, you simply look up each control via their name.