Skip to content

Instantly share code, notes, and snippets.

@danielrbradley
Created June 21, 2012 10:56
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save danielrbradley/2965119 to your computer and use it in GitHub Desktop.
ASP.NET MVC Enumeration Dropdown Extensions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace System.Web.Mvc.Html
{
public static class EnumDropdownExtenstions
{
/// <summary>
/// Returns an HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the value.</typeparam>
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
/// <param name="expression">
/// An expression that identifies the object that contains the properties to
/// display.
/// </param>
/// <returns>
/// An HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </returns>
/// <exception cref="System.ArgumentException">
/// The expression is not an enumeration type.
/// </exception>
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
return htmlHelper.EnumDropDownListFor(expression, value =>
{
return Regex.Replace(
Regex.Replace(
value.ToString(),
@"[a-z][A-Z]+",
m => string.Concat(m.Value[0], ' ', m.Value.Substring(1))),
@"[A-Z]{2,}[a-z]",
m => string.Concat(m.Value.Substring(0, m.Length - 2), ' ', m.Value.Substring(m.Length - 2)));
});
}
/// <summary>
/// Returns an HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the value.</typeparam>
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
/// <param name="expression">
/// An expression that identifies the object that contains the properties to
/// display.
/// </param>
/// <param name="displayValue">
/// A function to convert an enumeration value into a readable name.
/// </param>
/// <returns>
/// An HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </returns>
/// <exception cref="System.ArgumentException">
/// The expression is not an enumeration type.
/// </exception>
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Func<TProperty, string> displayValue)
{
return htmlHelper.EnumDropDownListFor(expression, displayValue, null, null);
}
/// <summary>
/// Returns an HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the value.</typeparam>
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
/// <param name="expression">
/// An expression that identifies the object that contains the properties to
/// display.
/// </param>
/// <param name="displayValue">
/// A function to convert an enumeration value into a readable name.
/// </param>
/// <returns>
/// An HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </returns>
/// <exception cref="System.ArgumentException">
/// The expression is not an enumeration type.
/// </exception>
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Func<TProperty, string> displayValue, object htmlAttributes)
{
return htmlHelper.EnumDropDownListFor(expression, displayValue, null, htmlAttributes);
}
/// <summary>
/// Returns an HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TProperty">The type of the value.</typeparam>
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
/// <param name="expression">
/// An expression that identifies the object that contains the properties to
/// display.
/// </param>
/// <param name="displayValue">
/// A function to convert an enumeration value into a readable name.
/// </param>
/// <returns>
/// An HTML select element for the property specified by the
/// expression, presenting the values with custom readable names.
/// </returns>
/// <exception cref="System.ArgumentException">
/// The expression is not an enumeration type.
/// </exception>
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Func<TProperty, string> displayValue, string optionLabel, object htmlAttributes)
{
Type enumType;
bool isOptional;
var propertyType = typeof(TProperty);
if (propertyType.IsEnum)
{
enumType = propertyType;
isOptional = false;
}
else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>) && propertyType.GetGenericArguments().Single().IsEnum)
{
enumType = propertyType.GetGenericArguments().Single();
isOptional = true;
}
else
throw new ArgumentException("property is not an enumeration type.", "expression");
var selected = expression.Compile().Invoke(htmlHelper.ViewData.Model);
var selectList = Enum.GetValues(enumType).Cast<TProperty>().OrderBy(p => p.ToString()).Select(p => new SelectListItem { Value = p.ToString(), Text = displayValue(p), Selected = p.Equals(selected) }).ToList();
if (isOptional)
selectList.Insert(0, new SelectListItem { Value = string.Empty, Text = string.Empty, Selected = selected.Equals(null) });
return htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes);
}
}
}
@uranium62
Copy link

Nice example but doesn't work Globalization.

@uranium62
Copy link

I implement Globalization!

@RoelRoel
Copy link

RoelRoel commented Apr 9, 2013

Great!
But it would be nice could if you could use the Display(Name = ...) attribute on enums. But that can be fixed when passing this as a function for displayValue:

I use: e => e.DisplayName() as parameter for the displayValue.

And created an extension method to the enum:

public static class EnumExtensions
{
    public static string DisplayName(this Enum value)
    {
        Type enumType = value.GetType();
        var enumValue = Enum.GetName(enumType, value);
        MemberInfo member = enumType.GetMember(enumValue)[0];

        var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
        var outString = ((DisplayAttribute)attrs[0]).Name; //TODO Null check

        if (((DisplayAttribute)attrs[0]).ResourceType != null)
        {
            outString = ((DisplayAttribute)attrs[0]).GetName();
        }

        return outString;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment