Реализация массива Enum to String Array TypeConverter в .NET - PullRequest
0 голосов
/ 17 декабря 2018

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

    // ...
}

Пожалуйста, примите во внимание, что я запрашиваюмногоразовое решение, которое может работать для любого типа enum.И мое перечисление в этом примере не имеет примененного атрибута [Flags], но решение должно позаботиться о том, чтобы перечисления имели его, поэтому, если элемент перечисления в массиве перечисления имеет перечисление с различными флагами, эти флаги (значениеимена) следует объединить, например, используя string.join () .

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Как упомянуто @NineBerry в его ответе , PropertyGrid уже показывает имена для значений перечисления.Однако я обнаружил, что существует странное обстоятельство, при котором он не будет этого делать ...

Поскольку мой исходный код написан на VB.NET, я помещу примеры кодов VB.NET для воспроизведенияпроблема.

Дело в том, что я получал значение из экземпляра класса WMI (в частности: Win32_DiskDrive.Capabilities ), который возвращает объект, который должен быть приведен к uint16.массив.Затем я приводил этот результирующий массив uint16 к моему типу enum.Для упрощения я не буду показывать код WMI, но объект, который представляет то, что я получал от WMI ...

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

Итак, при выполнении приведения типов и благодаря ответу @NineBerry,Я обнаружил, что по какой-то причине преобразователь типов по умолчанию TestProperty работает неправильно, а PropertyGrid показывает значения uint16 вместо имен значений-перечислений.

(обратите внимание, что при использовании DirectCast () или CType () в VB.NET, он не изменил поведение 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)
0 голосов
/ 17 декабря 2018

PropertyGrid уже показывает имена для значений enum.Он может даже правильно обрабатывать [Flags].Посмотрите пример ниже, используя форму с сеткой свойств по умолчанию и кнопкой по умолчанию, и ничего больше.

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.Вы, должно быть, делаете что-то не так с самого начала.

...