Enum을 지역화하고 WPF에서 콤보 상자 등에 바인딩하는 방법

11202 단어 C#WPF
Infragistics의 구성 요소를 만들고있는 사람이며 WPF/Xamarin.Forms에서 앱을 개발하는 사람이라면 이름을 듣지 못한 사람이 없을 정도로 유명한 Prism 커미터로 근육이 굉장하다 Brian Lagunas의 YouTube 채널에서 최근 이런 재료가 다루어졌습니다.

How to Bind an Enum to a ComboBox in WPF

이 동영상에서 Enum 의 요소를 간단하게 ComboBox 의 선택지로서 내는 방법이 소개되고 있었습니다만, 현지화는 고려하고 있지 않았기 때문에, 좋은 블로그 네타라고 생각하고 있었습니다.
그렇게 생각하면 오늘 이런 동영상이 오르고 있었습니다.

How to Localize Enums in C#

재료를 쓴 ぁ ぁ ぁ!

동영상의 방법 소개



마크업 확장으로 Enum 형의 값의 배열을 돌려주는 것을 만드는 것으로 이하와 같이 간단하게 쓸 수 있다.
<ComboBox ItemsSource="{Binding Source={local:EnumBindingSource {x:Type local:Status}}}" />

Enum 을 임의의 캐릭터 라인으로 변환하려면 , TypeConverter 를 사용해 Enum 가 WPF 의 컨트롤에 표시되는 처리를 커스터마이즈 해 DescriptionAttribute 가 있으면, 거기에 지정된 값을 사용한다고 하는 느낌이었습니다. 현지화는 LocalizedDescriptionAttirubute 를 사용해 자원의 정의되고 있는 형태와 키를 지정할 수 있는 독자적인 속성을 정의하는 느낌으로 하고 있었습니다.

과연, TypeConverter 의 존재를 잊고 있었습니다만, 이런 식으로도 사용할 수 있네요.

조금 개선?



동영상 내에서는 DescriptionAttribute 를 사용해 Enum 에 표시용 캐릭터 라인을 지정하고 있어, 현지화 가능하게 하는 경우는 자전의 현지화한 캐릭터 라인을 지정 가능한 속성을 자작하고 있었습니다만, 일단 표준 중에도 현지화 기능이 있는 속성으로서 DisplayAttribute 가 있으므로, 그쪽을 사용하면 독자 속성이 없어도 좋을 것 같아서 생각했습니다.

다만, 순수하게 현지화 가능한 표시명만을 제공하고 싶은 경우에는 오버스펙이므로 커스텀 속성 쪽이 좋을지도 모릅니다. 그렇지만 우선 해 봅시다.

TypeConverter 를 다음과 같이 DisplayAttribute 를 사용하게 하고…

EnumDisplayTypeConverter.cs
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Reflection;

namespace BindingEnums
{
    public class EnumDisplayTypeConverter : EnumConverter
    {
        public EnumDisplayTypeConverter(Type type) : base(type)
        {
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                if (value != null)
                {
                    var field = value.GetType().GetField(value.ToString());
                    if (field != null)
                    {
                        var attribute = field.GetCustomAttribute<DisplayAttribute>(false);
                        return attribute == null ? value.ToString() : attribute.GetName();
                    }
                }
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

    }
}

그리고, Enum 에 다음과 같이 Display 속성 첨부로 정의합니다.

Status.cs
using BindingEnums.Resources;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace BindingEnums
{
    [TypeConverter(typeof(EnumDisplayTypeConverter))]
    public enum Status
    {
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.Horrible))]
        Horrible,
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.Bad))]
        Bad,
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.SoSo))]
        SoSo,
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.Good))]
        Good,
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.Better))]
        Better,
        [Display(ResourceType = typeof(EnumResource), Name = nameof(EnumResource.Best))]
        Best,
    }
}

자원은 시간에 맞추어 적당히 준비해 두었습니다.



실행하면, 이런 느낌이 됩니다.



좋아.

요약



그렇다고 해서 스스로 자원으로부터 캐릭터 라인 가져오는 처리를 하지 않아도, 표준인 속성 중이라면 DisplayAttribute 당을 사용하면 자전에서 속성 만들지 않아도 되지만, 약간 DisplayAttribute 는 오버스펙감이 있다 는 부정할 수 없다…

소스 코드는 다음 리포지토리로 업그레이드했습니다.

그리고 Brian Lagunas 님의 YouTube 채널은 XAML 계열을 하고 있는 사람에게는 친밀한 화제로 영어를 들을 수 있고, 자동 생성 자막에서도 꽤 이케하고 있으므로 개인적으로 추천입니다.

Brian Lagunas의 YouTube 채널은 다음 링크에서 확인할 수 있습니다.

Brian Lagunas - YouTube

좋은 웹페이지 즐겨찾기