상세 컨텐츠

본문 제목

C# PropertyGrid에서 enum 적용 시 숫자 형태의 값 사용하기

프로그래밍/C#

by TickTack 2023. 4. 10. 11:40

본문

C#에서 enum을 PropertyGrid 등에서 사용 시에 다음 처럼 활용하고 싶을 때가 있습니다.

 

 

그러나 숫자 형태의 값은 enum에서 일반적인 방법으로는 사용할 수가 없습니다.

그래서 이번에는 문자 형태의 값이 아닌 숫자 형태의 값을 사용하는 방법에 대하여 알아보겠습니다.

 

아래 코드는 enum을 선언하는 코드입니다.

public enum Angle
{
    [Description("None")]
    None,
    [Description("90")]
    _90,
    [Description("180")]
    _180,
    [Description("270")]
    _270,
}

 

모든 항목위에 [Description("표시 할 문자")]를 선언해야 합니다.

숫자 형태의 값은 사용할 수 없기 때문에 앞에 _를 추가하여 문자로 인식하도록 하였습니다.

_가 아닌 *, -, +, @, #, % 등 대부분의 특수 문자들은 구문 오류가 발생하므로 _로 사용하는 것이 좋습니다.

None 항목은 Description을 추가하지 않고 테스트 해봤는데 동작은 잘 됐으나,

해외 포럼에서는 모든 항목에 추가해야 한다고 나와있는 부분때문에

예상치 못한 곳에서의 버그 유발 가능성이 우려되므로 모두 추가하여 사용하시는 것을 권장드립니다.

 

아래 코드는 생성해야 하는 클래스 입니다. 한 번 생성해놓고 여러 군데서 사용하면 될 것으로 보입니다.

public class NumberofStringConverter : EnumConverter
{
    private Type enumType;

    public NumberofStringConverter(Type type) : base(type)
    {
        enumType = type;
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
    {
        return destType == typeof(string);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture,
                                     object value, Type destType)
    {
        FieldInfo fi = enumType.GetField(Enum.GetName(enumType, value));
        DescriptionAttribute dna = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
                                    typeof(DescriptionAttribute));
        if (dna != null)
            return dna.Description;
        else
            return value.ToString();
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type srcType)
    {
        return srcType == typeof(string);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture,
                                       object value)
    {
        foreach (FieldInfo fi in enumType.GetFields())
        {
            DescriptionAttribute dna = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
                                        typeof(DescriptionAttribute));
            if ((dna != null) && ((string)value == dna.Description))
                return Enum.Parse(enumType, fi.Name);
        }
        return Enum.Parse(enumType, (string)value);
    }
}

 

위의 클래스는 자세히 분석하지는 않았기 때문에 간단하게 설명드려보면..

EnumConverter 클래스를 상속받아서 4개의 메서드를 override를 통하여 재정의 하고 있는 코드입니다.

 

그 다음 enum 타입을 속성으로 활용할 때 다음과 같이 해주어야 합니다.

[DefaultValue(0)]
[TypeConverter(typeof(NumberofStringConverter))]
public Angle RotationAngle
{
    get { return angle; }
    set { angle = value; }
}

 

DefaultValue는 초기 값을 0으로 설정한다는 의미입니다. (Angle enum 기준 None이 됩니다.)

핵심은 TypeConverter입니다. 인자로는 위에 생성한 클래스를 Type 형태로 주고 있습니다.

이렇게 적용하면 맨 위의 콤보박스 이미지처럼 활용할 수 있습니다.

 

단, RotationAngle.ToString() 처럼 내부에서 데이터로 활용하게 되면 _90, _180 처럼 원래 형태로 나오기 때문에

RotationAngle.ToString().Replace("_", "")와 같은 추가적인 작업이 필요합니다.

 

이상으로 C# enum에서 숫자 형태로 값을 사용하는 방법에 대하여 알아보았습니다.

관련글 더보기

댓글 영역