How to localize an Enum and bind it to a combo box etc in WPF

2 minute read

If you’re a maker of Infragistics components and an app developer with WPF / Xamarin.Forms, you’ve never heard of a name. Prism’s committer and muscular Brian Lagunas recently posted on YouTube. Such a story was taken up.

How to Bind an Enum to a ComboBox in WPF

This video showed how to easily put the Enum element out as a ComboBox option, but I didn’t consider localization, so I thought it was a good blog post.
When I thought so, this video was posted today.

How to Localize Enums in C#

I wore a story! !!

Introduction of the method in the video

You can easily write the following by creating a markup extension that returns an array of Enum type values.

<ComboBox ItemsSource="{Binding Source={local:EnumBindingSource {x:Type local:Status}}}" />

To convert an Enum to an arbitrary string, I used TypeConverter to customize the way the Enum appears in the WPF control, and if there was a DescriptionAttribute, I felt like using the value specified there. Localization feels like using LocalizedDescriptionAttirubute to define its own attributes that allow you to specify the defined type and key of the resource.

I see, I forgot about the existence of TypeConverter, but it can be used in this way as well.

A little improvement?

In the video, I used DescriptionAttribute to specify the display string for Enum, and if I wanted to make it localizable, I made my own attribute that can specify my own localized string, but for the time being, it is also in the standard There is DisplayAttribute as an attribute with localization function, so I thought that it would be okay if I used it without my own attribute.

However, if you want to provide only purely localizable display names, custom attributes may be better as they are over-engineered. But let’s do it for the time being.

Make TypeConverter use DisplayAttribute like this …

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

    }
}

Then, define it in the Enum with the Display attribute as shown below.

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

I prepared the resources appropriately in time.

image.png

When executed, it looks like this.

image.png

How nice.

Summary

So you don’t have to do the process of fetching the character string from the resource by yourself, but if you use DisplayAttribute in the standard attribute, you do not have to create the attribute yourself, but DisplayAttribute has a feeling of over-specification. I can’t deny that …

The source code has been uploaded to the following repository.

https://github.com/runceel/BindingEnums

Also, Brian Lagunas’s YouTube channel is a familiar topic for those who are doing XAML-related things, and I can listen to English, and the automatically generated subtitles are pretty cool, so I personally recommend it.

Brian Lagunas’s YouTube channel can be found at the link below.

Brian Lagunas - YouTube

Tags: ,

Updated: