在.NET

时间:2018-12-17 11:36:36

标签: c# .net vb.net enums typeconverter

在C#或VB.NET中,在WinForms下,我有一个返回枚举数组的属性。查看示例:

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};

默认情况下,PropertyGrid会将值显示为int [],例如:{0,1,2}而不是枚举值名称,例如:{“ Name1”,“ Name2”,“ Name2 “},这是我想要实现的视觉效果...

因此,我想设计一个TypeConverter,它可以返回带有值名称的字符串数组,并像这样应用它:

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

换句话说,如果我的属性在PropertyGrid中这样表示:

enter image description here

我想要这个:

enter image description here


我面临的最大问题是尝试从自定义类型转换器类中检索枚举的类型,以便能够获取该枚举的值名称。我只能得到数组的原始数据类型(例如:int [],uint16 []等)。

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;
    }

    // ...
}

请考虑到我正在寻求可用于任何枚举的可重用解决方案。并且,在此示例中,我的枚举没有应用[Flags]属性,但是解决方案应该考虑具有该属性的枚举,因此,如果枚举数组的枚举项是具有多个标志的枚举,则这些标志(值名称)应进行连接,例如使用 string.join()

2 个答案:

答案 0 :(得分:1)

PropertyGrid已经显示了enum值的名称。它甚至可以正确处理[Flags]。使用具有默认PropertyGrid和默认按钮且没有其他内容的表单,请参见下面的示例。

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

请提供一些示例代码,这些代码可以重现PropertyGrid中未显示枚举名称。首先,您一定在做错事。

答案 1 :(得分:1)

正如@NineBerry在his answer中提到的那样, PropertyGrid 已经显示了枚举值的名称。但是,我发现在这种情况下存在一种奇怪的情况是不会这样做的。

由于我的原始源代码是用VB.NET编写的,因此我将放置VB.NET示例代码来重现此问题。

问题是我正在从WMI类的实例(具体是Win32_DiskDrive.Capabilities)的实例中获取一个值,该实例返回一个需要转换为uint16数组的对象。然后,我将生成的uint16数组转换为我的枚举类型。为简化起见,我不会显示WMI代码,而是显示一个代表我从WMI中得到的内容的对象...

Dim wmiValue As Object = {1US, 2US, 3US}
Dim castedValue As UShort() = DirectCast(wmiValue, UShort())
TestProperty = DirectCast(castedValue, TestEnum())

因此,在进行类型转换时,并感谢@NineBerry的回答,我发现由于某种原因, TestProperty 的默认类型转换器出错,并且 PropertyGrid 显示uint16值而不是枚举值名称。

(请注意,在VB.NET中使用 DirectCast() CType(),它并没有更改 PropertyGrid 行为。)

要解决该错误,我结束了使用 Array.ConvertAll(),然后 PropertyGrid 正确显示了值名称...

Dim wmiValue As Object = {1US, 2US, 3US}
Dim castedValue As UShort() = DirectCast(wmiValue, UShort())
TestProperty = Array.ConvertAll(castedValue,
                                Function(value As UShort)
                                    Return DirectCast(value, TestEnum)
                                End Function)