mandag den 19. marts 2012

Localizing enums in MVC3

Enums are great for a developer to easily remember and set various constants. Sometimes you also need to present the enum to your user. Often this is done with a Listbox or a Combobox where the user chooses between the enums. By default .Net4 doesn't support localizing or even changing the text values to make it readable and understandable by your users.

Here's how you can create an enum, localize it and present it i your view.

Create your Enum:
public enum FacebookModules
        {
            Feed = 1,
            Posts,
            Events,
            Gallery
        }
Create an extension to the enum class and add a new description value to it:
public class LocalizedEnumAttribute : DescriptionAttribute
    {
        private PropertyInfo _nameProperty;
        private Type _resourceType;

        public LocalizedEnumAttribute(string displayNameKey)
            : base(displayNameKey)
        {

        }

        public Type NameResourceType
        {
            get
            {
                return _resourceType;
            }
            set
            {
                _resourceType = value;

                _nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public);
            }
        }

        public override string Description
        {
            get
            {
                //check if nameProperty is null and return original display name value
                if (_nameProperty == null)
                {
                    return base.Description;
                }

                return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null);
            }
        }
    }

    public static class EnumExtender
    {
        public static string GetLocalizedDescription(this Enum @enum)
        {
            if (@enum == null)
                return null;

            string description = @enum.ToString();

            FieldInfo fieldInfo = @enum.GetType().GetField(description);
            DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Any())
                return attributes[0].Description;

            return description;
        }
    }

You can now add your new attribute to your enums by using this annotation:
[LocalizedEnum("Facebook_Feed", NameResourceType = typeof(Resources.Resources))]

Your enum should look a bit like this:
public enum FacebookModules
        {
            [LocalizedEnum("Facebook_Feed", NameResourceType = typeof(Resources.Resources))]
            Feed = 1,

            [LocalizedEnum("Facebook_Posts", NameResourceType = typeof(Resources.Resources))]
            Posts,

            [LocalizedEnum("Facebook_Events", NameResourceType = typeof(Resources.Resources))]
            Events,

            [LocalizedEnum("Facebook_Gallery", NameResourceType = typeof(Resources.Resources))]
            Gallery
        }

From here on you can simply call the method MyEnumInstance.GetLocalizedDescription() to get your localized name. If no ressource file is setup or the value can't be found in it, it will default to the LocalizedEnum name.

Now if you want to use this in a standard combobox in your MVC view you can do something like this:

@Html.DropDownListFor(model => model.ContentType, Enum.GetValues(typeof(Enums.FacebookModules)).Cast<enums.facebookmodules>().Select(v => new SelectListItem
                       {
                           Text = v.GetLocalizedDescription(),
                           Value = v.ToString().Replace("_", " ")
                       }))

Thats it!

Ingen kommentarer:

Send en kommentar