Search code examples
c#.netvb.netenumstypeconverter

Implementing an Enum Array to String Array TypeConverter in .NET


In C# or VB.NET, under WinForms, I have a property that returns an array of a enum. See an example:

public enum TestEnum: int {
    Name1 = 0,
    Name2 = 1,
    Name3 = 2
} // Note that the enum does not apply for the [Flags] attribute.

public TestEnum[] TestProperty {get; set;} = 
    new[] {TestEnum.Name1, TestEnum.Name2, TestEnum.Name3};

By default, a PropertyGrid will show the values as int[], like: {0, 1, 2} instead of the enumeration value names, like: {"Name1", "Name2", "Name2"}, which is the visual representation that I would like to acchieve...

So, I would like to design a TypeConverter that could be able to return a string array with the value names, and apply it like this:

[TypeConverter(typeof(EnumArrayToStringArrayTypeConverter))]
public TestEnum[] TestProperty {get; set;} = 
    new[] {TestEnum.Name1, TestEnum.Name2, TestEnum.Name3};

In other words, If my property is represented like this in a PropertyGrid:

enter image description here

I would like to have this:

enter image description here


The biggest problem I'm facing is trying to retrieve the type of the enum from the custom type-converter class, to be able get the value names of that enum. I only can get the primitive data type of the array (like: int[], uint16[], etc)...

public class EnumArrayToStringArrayTypeConverter : TypeConverter {
    // ...

    public override object ConvertTo(ITypeDescriptorContext context, 
                                     CultureInfo culture, 
                                     object value, 
                                     Type destinationType) {

        if (destinationType == null) {
            throw new ArgumentNullException(nameof(destinationType));
        }

        try {
            // This will return the array-type for the 
            // primitive data type of the declared enum, 
            // such as int[], uint16[], etc.
            Type t = value.GetType(); 

            // I'm stuck at this point. 
            // ...

        } catch (Exception ex) {

        }

        return null;
    }

    // ...
}

Please take into account that I'm asking for a reusable solution that can work for any kind of enum. And, my enum in this example does not have the [Flags] attribute applied, but a solution should care about enums having it, so, If a enum item of the enum array is a enum that has various flags, those flags (the value names) should be concatenated for example using string.join().


Solution

  • The PropertyGrid does already show the names for the enum values. It can even handle [Flags] correctly. See the sample below using a form with a default PropertyGrid and a default button and nothing else.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        [Flags]
        public enum TestEnum : int
        {
            Name1 = 0,
            Name2 = 1,
            Name3 = 2
        } 
    
        public class TestObject
        {
            public string Name { get; set; } = "Hello World";
            public TestEnum[] TestProperty { get; set; } =
                new[] { TestEnum.Name1, TestEnum.Name2 | TestEnum.Name3, TestEnum.Name3 };
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            TestObject o = new TestObject();
            propertyGrid1.SelectedObject = o;
        }
    }
    

    enter image description here enter image description here

    Please supply some example code that can reproduce that the enum names are not shown in the PropertyGrid. You must be doing something wrong in the first place.