Search code examples
c#.netwinformspropertygrid

Combine ExpandableObjectConverter with Drop Down List


I have a nullable property in my class and I want user to be able to create its instance using PropertyGrid. Which I did using ExpandableObjectConverter.

When instance is created it automatically appears in PropertyGrid with posibility to expand it and change its properties' values.

Still I need to type some string to create a new instance.

That is why I am wondering if it is possible to combine ExpandableObjectConverter with DropDownList. So user would be able to select one of the existing values.


Solution

  • You need to create a new ExpandableObjectConverter, supporting standard values.

    Example

    As an example, lets say, xlass A has a property of type B and we like to let the user to choose some predefined values for B from a drop-down list in property grid.

    After you select something from dropdown, the B will be initialized and you still can edit C:

    enter image description here

    Here is the definition for A and B:

    public class A
    {
        [TypeConverter(typeof(BConverter))]
        public B B { get; set; }
    }
    public class B : ICloneable
    {
        [RefreshProperties(RefreshProperties.All)]
        public string C { get; set; }
        public object Clone()
        {
            return new B { C = this.C };
        }
        public override string ToString()
        {
            return C;
        }
    }
    

    Here is the custom ExpandableObjectConverter:

    public class BConverter : ExpandableObjectConverter
    {
        B[] values = new B[] { new B { C = "Something" }, new B { C = "Something else" } };
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;
            return base.CanConvertFrom(context, sourceType);
        }
        public override object ConvertFrom(ITypeDescriptorContext context, 
            System.Globalization.CultureInfo culture, object value)
        {
            var result = values.Where(x => $"{x}" == $"{value}").FirstOrDefault();
            if (result != null)
                return result.Clone();
            return base.ConvertFrom(context, culture, value);
        }
        public override bool GetStandardValuesSupported(ITypeDescriptorContext c)
        {
            return true;
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext c)
        {
            return true;
        }
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext c)
        {
            return new StandardValuesCollection(values);
        }
    }