Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have the designer serialize a collection of objects in WinForms?

I have a class:

public class Filter
{
    public Filter (string name, string value)
    {
        Name = name;
        Value = value;
    }

    public string Name {get; private set;}
    public string Value {get; set;}
}

And a collection class:

public class FilterCollection : Collection<Filter>
{
   // code elided
}

My component class:

public class MyComponent : Component
{
    // ...

    [Editor(typeof(FilterEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public FilterCollection Filters { get; set; }

    // ...
}

The problem is that the collection is not serialized correctly by the designer.

I'm sure I'm missing something but I don't know what.

ADDITIONAL INFO

What I would like the designer.cs file to have is something along the following:

myComponent.Filters.Add (new Filter ("some name", "some value"));
myComponent.Filters.Add (new Filter ("other name", "other value"));

Is this feasible?

like image 675
Stécy Avatar asked May 02 '12 13:05

Stécy


1 Answers

Ok, problem solved.

I needed to use a TypeConverter for my Filter class:

internal class FilterConverter : TypeConverter
{
    public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo (context, destinationType);
    }

    public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor) && value is Filter)
        {
            ConstructorInfo constructor = typeof (Filter).GetConstructor (new[] {typeof (string), typeof (string)});

            var filter = value as Filter;
            var descriptor = new InstanceDescriptor (constructor, new[] {filter.Name, filter.Value}, true);

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

The converter is then added to the Filter class like so:

[TypeConverter(typeof(FilterConverter))]
public class Filter
{
    // ...
}

The important thing to note here is the creation of an instance descriptor with the required parameters for the Filter constructor. Also, you need to set the last parameter (isComplete) of the InstanceDescriptor constructor to true.

like image 161
Stécy Avatar answered Oct 26 '22 23:10

Stécy