Search code examples
c#asp.net-mvc-3razor

MVC3 Razor DropDownListFor Enums


Trying to get my project updated to MVC3, something I just can't find:

I have a simple datatype of ENUMS:

public enum States()
{
  AL,AK,AZ,...WY
}

Which I want to use as a DropDown/SelectList in my view of a model that contains this datatype:

public class FormModel()
{
    public States State {get; set;}
}

Pretty straight forward: when I go to use the auto-generate view for this partial class, it ignores this type.

I need a simple select list that sets the value of the enum as the selected item when I hit submit and process via my AJAX - JSON POST Method.

And than the view (?!):

    <div class="editor-field">
        @Html.DropDownListFor(model => model.State, model => model.States)
    </div>

Solution

  • I've just made one for my own project. The code below is part of my helper class, I hope that I got all methods needed. Write a comment if it doesn't work, and I'll check again.

    public static class SelectExtensions
    {
    
        public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            if (expression.Body.NodeType == ExpressionType.Call)
            {
                MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
                string name = GetInputName(methodCallExpression);
                return name.Substring(expression.Parameters[0].Name.Length + 1);
    
            }
            return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
        }
    
        private static string GetInputName(MethodCallExpression expression)
        {
            // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
            MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
            if (methodCallExpression != null)
            {
                return GetInputName(methodCallExpression);
            }
            return expression.Object.ToString();
        }
    
        public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
        {
            string inputName = GetInputName(expression);
            var value = htmlHelper.ViewData.Model == null
                ? default(TProperty)
                : expression.Compile()(htmlHelper.ViewData.Model);
    
            return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
        }
    
        public static SelectList ToSelectList(Type enumType, string selectedItem)
        {
            List<SelectListItem> items = new List<SelectListItem>();
            foreach (var item in Enum.GetValues(enumType))
            {
                FieldInfo fi = enumType.GetField(item.ToString());
                var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
                var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
                var listItem = new SelectListItem
                    {
                        Value = ((int)item).ToString(),
                        Text = title,
                        Selected = selectedItem == ((int)item).ToString()
                    };
                items.Add(listItem);
            }
    
            return new SelectList(items, "Value", "Text", selectedItem);
        }
    }
    

    Use it as:

    Html.EnumDropDownListFor(m => m.YourEnum);
    

    Update

    I've created alternative Html Helpers. All you need to do to use them is to change your baseviewpage in views\web.config.

    With them you can just do:

    @Html2.DropDownFor(m => m.YourEnum);
    @Html2.CheckboxesFor(m => m.YourEnum);
    @Html2.RadioButtonsFor(m => m.YourEnum);
    

    More info here: http://blog.gauffin.org/2011/10/first-draft-of-my-alternative-html-helpers/