701

I'm trying to use the Html.DropDownList extension method but can't figure out how to use it with an enumeration.

Let's say I have an enumeration like this:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

How do I go about creating a dropdown with these values using the Html.DropDownList extension method?

Or is my best bet to simply create a for loop and create the Html elements manually?

ArunPratap
  • 4,020
  • 7
  • 22
  • 39
Kevin Pang
  • 39,694
  • 37
  • 117
  • 169

36 Answers36

869

For MVC v5.1 use Html.EnumDropDownListFor

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

For MVC v5 use EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

For MVC 5 and lower

I rolled Rune's answer into an extension method:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

This allows you to write:

ViewData["taskStatus"] = task.Status.ToSelectList();

by using MyApp.Common

Marcos Dimitrio
  • 5,592
  • 3
  • 33
  • 56
Martin Faartoft
  • 3,275
  • 2
  • 16
  • 11
  • 13
    I couldnt get it worked, could you please help. When i do Post.PostType.ToSelectList(); it doesnt recognise the extension ? – Barbaros Alp Dec 18 '09 at 13:41
  • 3
    I could not get this to work either. Is Status your Enum Property on the task class? Isn't this one of the enumerated values? – Daryl Jul 05 '10 at 15:42
  • 1
    Great! To questions above, yes it is one of the enum values, that becomes the 'selected value'. You can also do: ((TypesEnum)typeId).ToSelectList(); – Seba Illingworth Mar 19 '11 at 02:29
  • make sure if you've yet to add the namespace for your helpers you add it via a 'using ;' directive in your razor – TodK Mar 28 '11 at 14:35
  • 1
    One caveat: because the extension method does not have any constraints, it will extend every type. This is unavoidable because you do not know what the enum types are and you couldn't constrain on them anyway (I believe). So you will find that int, for example, now has ToSelectList method. I made the same mistake and think, for that reason, it is better as an Html extension. – Rob Kent Apr 19 '11 at 18:56
  • 9
    You can restrict it a little bit with: where T : struct, IConvertible See: http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-to-an-enum – Richard Garside May 17 '11 at 15:29
  • 8
    This is cool. If anyone is struggling w/ implementation here's how I did it. Added an EnumHelpers class to the HtmlHelpers folder. Used the above code. Added the namespace per @TodK recommendation: . Then I used it in a razor page like such: @Html.DropDownListFor(model => model.Status, @Model.Status.ToSelectList()) HTH – Jeff Borden Jul 25 '12 at 19:28
  • 1
    Used @Html.DropDownListFor( model => model.SelectedCategory, Model.SelectedCategory.ToSelectList()} Where SelectedCategory is a an Enum-type. – Per G Jun 24 '13 at 12:56
  • 1
    Added generic type constraints from Ricardo Nolde's and Lisa's comment on http://stackoverflow.com/a/79903/221708. – Daniel Schilling Jul 18 '13 at 20:43
  • 6
    Note that in newer `ASP.NET MVC` there is a native way: http://stackoverflow.com/a/22295360/1361084 – Ofiris Jan 28 '15 at 16:22
  • "Return type 'System.Int64' is not supported. Parameter name: expression" – juFo Apr 17 '18 at 09:51
365

I know I'm late to the party on this, but thought you might find this variant useful, as this one also allows you to use descriptive strings rather than enumeration constants in the drop down. To do this, decorate each enumeration entry with a [System.ComponentModel.Description] attribute.

For example:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

Here is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;

 ...

 private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        Type realModelType = modelMetadata.ModelType;

        Type underlyingType = Nullable.GetUnderlyingType(realModelType);
        if (underlyingType != null)
        {
            realModelType = underlyingType;
        }
        return realModelType;
    }

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        Type enumType = GetNonNullableModelType(metadata);
        IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

        IEnumerable<SelectListItem> items = from value in values
            select new SelectListItem
            {
                Text = GetEnumDescription(value),
                Value = value.ToString(),
                Selected = value.Equals(metadata.Model)
            };

        // If the enum is nullable, add an 'empty' item to the collection
        if (metadata.IsNullableValueType)
            items = SingleEmptyItem.Concat(items);

        return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    }

You can then do this in your view:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

Hope this helps you!

**EDIT 2014-JAN-23: Microsoft have just released MVC 5.1, which now has an EnumDropDownListFor feature. Sadly it does not appear to respect the [Description] attribute so the code above still stands.See Enum section in Microsoft's release notes for MVC 5.1.

Update: It does support the Display attribute [Display(Name = "Sample")] though, so one can use that.

[Update - just noticed this, and the code looks like an extended version of the code here: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/, with a couple of additions. If so, attribution would seem fair ;-)]

Kolappan N
  • 2,178
  • 2
  • 26
  • 31
SimonGoldstone
  • 4,842
  • 3
  • 21
  • 36
  • 28
    +1 I found this most useful of all the answers here. I was able to turn this in to a highly reusable piece of code. Thank you! – Ed Charbeneau Jul 19 '11 at 14:23
  • 43
    Visual Studio has a strange bug where if you don't reference `System.Web.Mvc.Html` then it says that `DropDownListFor` can't be found, but neither can it resolve it. You have to manually do `using System.Web.Mvc.Html;`. Just so y'know. – Kezzer Oct 27 '11 at 13:29
  • 1
    I have a variant of this in a gist which we use in all of our projects: https://gist.github.com/1287511 – kamranicus Jan 09 '12 at 18:45
  • Nice but how do you add a first element with the value "-- Select --" to the drop-down list? I don't want to include this element as part of my enum. – thd Mar 22 '12 at 22:12
  • 1
    Great solution, thanks, would be even better if you can cache the results of GetEnumDescription – M. Mennan Kara Aug 20 '12 at 13:52
  • Your provided code doesnt work for MVC 4, your view code results with "The call is ambiguous between the following methods or properties" and then list the two long EnumDropDownListFor method names and props. – Marc Sep 14 '12 at 18:05
  • 17
    The new MVC 5.1 EnumDropDownListFor doesn't use [Description("")] but it does use [Display(Name = "")]! Enjoy :) – Supergibbs Feb 28 '14 at 18:51
  • Beautiful. Had to google a bit to find how to put it all together though. http://stackoverflow.com/questions/10998827/custom-html-helpers-in-mvc-4 – Bjørn Otto Vasbotten Apr 23 '14 at 20:58
  • I think that the code `Selected = value.Equals(metadata.Model)` won't really affect because MVC will render the dropdown's selected value according to the model's property value inside the expression variable. – BornToCode Nov 23 '15 at 18:20
  • Take a look at this: http://www.codeproject.com/Articles/776908/Dealing-with-Enum-in-MVC – Cas Bloem Jan 18 '16 at 21:09
207

In ASP.NET MVC 5.1, they added the EnumDropDownListFor() helper, so no need for custom extensions:

Model:

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

View:

@Html.EnumDropDownListFor(model => model.MyEnum)

Using Tag Helper (ASP.NET MVC 6):

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Ofiris
  • 5,727
  • 2
  • 32
  • 56
  • 3
    You should create a new question that is specific to MVC 5.1 and put this as the answer, then send me a link to the post so that I may upvote an favorite. – Kevin Heidt Mar 29 '15 at 19:44
  • 2
    What I don't like about EnumDropDownListFor() is that it saves into the DB the int value of the enum, not the text, so if you ever choose to add a new enum item, it must necessarily go at the end of the list, so as not to loose the relationship of the saved database int values to original positions of the enum items. That is an unnecessary restriction if the text is saved. Plus, I rather be able to look at the db and see a text, rather than ints where I then have to lookup the text values elsewhere. Otherwise this html helper is very convenient to use. – Giovanni May 22 '15 at 15:57
  • 2
    @Giovanni - you can specify your own numerical values. – Tommy Jan 24 '16 at 20:50
  • it doesn't supper enum [Flags] yet :( – mejiamanuel57 Jul 22 '16 at 02:46
  • 1
    @Giovanni Strict design should assign value for each enum entry (if it's important), otherwise the value should not matter (and so placing the new ones at the end should not be a problem). Saving int values is better when it comes to saving storage and increasing performance (when performing some search). – King King Nov 04 '16 at 08:30
  • How to define default? I had to use `@Html.DropDownListFor(m => m.MyProperty, @Html.GetEnumSelectList(typeof(MyTypes.MyModel)))` – MushyPeas Dec 22 '16 at 12:31
131

I bumped into the same problem, found this question, and thought that the solution provided by Ash wasn't what I was looking for; Having to create the HTML myself means less flexibility compared to the built-in Html.DropDownList() function.

Turns out C#3 etc. makes this pretty easy. I have an enum called TaskStatus:

var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
               select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);

This creates a good ol' SelectList that can be used like you're used to in the view:

<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>

The anonymous type and LINQ makes this so much more elegant IMHO. No offence intended, Ash. :)

Chandan Kumar
  • 4,017
  • 3
  • 36
  • 58
Rune Jacobsen
  • 9,297
  • 11
  • 51
  • 72
  • good answer! i was hoping someone would use linq and the SelectList :) Glad i checked here first! – Pure.Krome Mar 22 '09 at 02:50
  • 1
    ID = s give me the DataTextField not the value ? What might be the reason ? Thank you – Barbaros Alp Dec 18 '09 at 19:09
  • 1
    Rune, I used this same method and the DropDownList DOES render yet when it posts to the server, it doesn't save the value I had selected. – clockwiseq Nov 23 '11 at 17:31
  • 5
    @BarbarosAlp For ID to be a number you'll need to cast the enum to an int: `select new { ID = (int)s, Name = s.ToString() };` – Keith Dec 01 '11 at 20:05
  • This is the answer I like the most because of its simplicity. Shame you didn't receive enough credit since the selected answer used your solution. – anar khalilov Nov 15 '13 at 09:07
  • @Keith, if you use generics instead of a fixed `enum`, Visual Studio won't let you do that cast. It tells you `Cannot convert type 'TEnum' to 'int'`. :( (I'm using the accepted answer code, BTW) – Andrew Apr 29 '15 at 04:24
66

Here is a better encapsulated solution:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

Say here is your model:

enter image description here

Sample Usage:

enter image description here

Generated UI: enter image description here

And generated HTML

enter image description here

The Helper Extension Source Code snap shot:

enter image description here

You can download the sample project from the link I provided.

EDIT: Here's the code:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name="enumType">Type of the enum.</param>
    /// <param name="selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}
Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Emran Hussain
  • 9,974
  • 5
  • 36
  • 44
  • 2
    Just my opinion, but I think this answer is much cleaner than the accepted answer. I particularly like the option of using the Description attribute. I added the code so that people can copy/paste it without downloading. – Ben Mills Jul 18 '13 at 20:31
  • Call the extension method as EnumDropDownListFor rather than DropDownListFor Usage:-> @Html.EnumDropDownListFor(x => x.Gender) – sandeep talabathula Jul 13 '14 at 12:53
  • For Someone Looking for Adding one more element "Please Select" return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected,firstElement),"Please Select"); – Sandeep Aug 08 '14 at 21:22
  • 1
    Works fine! However, on the Details page, the DisplayFor() shows the enum's selected value instead of the corresponding description. I suppose this calls for an overload for DisplayFor() for enum type. Anybody has solution for this? – corix010 Jan 21 '16 at 16:02
  • +a million kudos for the graphics – swaglord mcmuffin' May 20 '21 at 09:18
48

Html.DropDownListFor only requires an IEnumerable, so an alternative to Prise's solution is as follows. This will allow you to simply write:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[Where SelectedItemType is a field on your model of type ItemTypes, and your model is non-null]

Also, you don't really need to genericize the extension method as you can use enumValue.GetType() rather than typeof(T).

EDIT: Integrated Simon's solution here as well, and included ToDescription extension method.

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}
Zaid Masud
  • 12,359
  • 8
  • 62
  • 84
  • Doesn't work for me ('System.NullReferenceException: Object reference not set to an instance of an object.')... My 'Model' is null... probably has something to do with 'GetNonNullableModelType' which Simon has it included – Learner Mar 24 '12 at 20:31
  • @Cristi, you are right this solution is not intended to be used in a condition where your Model is null. I try to avoid such a design in general and initialize to an "Empty" model when that's the case. – Zaid Masud Mar 26 '12 at 09:43
  • Well, I am new to asp mvc, but i have quite experience in .Net . Thank you, I will look into that you were suggesting. Btw your ToDescription extension is far outside of 'Enum' scope. I guess goes well for the 'Object' itself. This is what I used when I took Simon's code and cleaned it up a bit more. – Learner Mar 26 '12 at 20:05
  • @Cristi it is difficult to understand what you mean by "far outside of 'Enum' scope" but it sounds like you're saying that the ToDescription extension method is not strongly typed to the ItemTypes enum? This is intentional and makes the extension method generically usable by all enums. If you are comparing it to a generic extension method, there are pros and cons of each approach. In particular, if you generecize you cannot make it constrained on enums alone. – Zaid Masud Mar 27 '12 at 11:26
  • First of all, your code is ok, you didn't do wrong. Is just that I prefer things which are more generic and logical too. My personal opinion is that there is no need to create this extension to the Enum, since there is a more generic Object (Enum: Object) which this extension applies better to. You could still use the rest of the code, this extension will have higher adhesion if is 'ToDescription(this Object value)'. Hope is more clear now. – Learner Mar 30 '12 at 11:45
  • 1
    Great, with thanks. I changed value.ToString to use an extension FromCamelCase in case there was no description. That is how I roll :) – Valamas Feb 18 '13 at 01:41
33

So without Extension functions if you are looking for simple and easy.. This is what I did

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

where XXXXX.Sites.YYYY.Models.State is an enum

Probably better to do helper function, but when time is short this will get the job done.

Marty Trenouth
  • 3,592
  • 6
  • 32
  • 41
  • Nice this worked populating the dropdown but how do you set the default selected value in the Razor syntax for Html.DropDownListFor? I want to show a table with combo boxes of enums and I need to set the selected value as well according to what it was before. – Johncl Sep 23 '11 at 14:20
  • 2
    Should be able to pass a second parameter with the selected value to the new SelectList(IEnumerable,object) function. MSDN Dococumentation: http://msdn.microsoft.com/en-us/library/dd460123.aspx – Marty Trenouth Sep 23 '11 at 17:26
24

Expanding on Prise and Rune's answers, if you'd like to have the value attribute of your select list items map to the integer value of the Enumeration type, rather than the string value, use the following code:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

Instead of treating each Enumeration value as a TEnum object, we can treat it as a object and then cast it to integer to get the unboxed value.

Note: I also added a generic type constraint to restrict the types for which this extension is available to only structs (Enum's base type), and a run-time type validation which ensures that the struct passed in is indeed an Enum.

Update 10/23/12: Added generic type parameter for underlying type and fixed non-compilation issue affecting .NET 4+.

Nathan Taylor
  • 23,720
  • 17
  • 90
  • 152
  • Thanks! This was the answer I needed. I'm storing an Enum's integer value as a column in the database and this solution seems to be working perfectly. – grimus Aug 11 '10 at 06:40
  • but what if you are storing a char and not an int? which is my case. obviously i could change (int) to (char) but how about making this generic as well. how to do that? – Stefanvds Sep 21 '10 at 12:46
  • @Stefandvds This is a great question in regards to casting to the correct represented type. Based on the tests I just performed it would seem the only way you would be able to achieve this would be by specifying the actual type as another type parameter. `ToSelectList(this TEnum enumObj) { ... }` – Nathan Taylor Sep 21 '10 at 13:19
  • @Stefandvds [See this question](http://stackoverflow.com/questions/3760933/how-to-determine-the-represented-type-of-enum-value/3760973). – Nathan Taylor Sep 21 '10 at 14:11
  • If your enum's values are int, you can simply use `Value = Convert.ToInt32(e)`. `(int)e` doesn't compile. :( – Andrew Apr 29 '15 at 04:38
11

A super easy way to get this done - without all the extension stuff that seems overkill is this:

Your enum:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

Inside of your controller bind the Enum to a List:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

After that throw it into a ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

Finally simply bind it to the View:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

This is by far the easiest way I found and does not require any extensions or anything that crazy.

UPDATE: See Andrews comment below.

Louie Bacaj
  • 1,329
  • 12
  • 18
  • 3
    This only works if you haven't assigned any value to your enum. If you had `Level1 = 1`, then the dropdown's value would be `"Level1"` instead of `1`. – Andrew Apr 29 '15 at 04:43
11

To solve the problem of getting the number instead of text using Prise's extension method.

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}
ceedee
  • 186
  • 1
  • 3
  • That's what I was looking for, although it's a but uglier than I thought it needed to be. I wonder why Visual Studio won't let you directly cast `e` to `int`. – Andrew Apr 29 '15 at 04:26
  • Or you could simply use `ID = Convert.ToInt32(e)`. – Andrew Apr 29 '15 at 04:39
11

The best solution I found for this was combining this blog with Simon Goldstone's answer.

This allows use of the enum in the model. Essentially the idea is to use an integer property as well as the enum, and emulate the integer property.

Then use the [System.ComponentModel.Description] attribute for annotating the model with your display text, and use an "EnumDropDownListFor" extension in your view.

This makes both the view and model very readable and maintainable.

Model:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

View:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

Extension (directly from Simon Goldstone's answer, included here for completeness):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
        {
            Type realModelType = modelMetadata.ModelType;

            Type underlyingType = Nullable.GetUnderlyingType(realModelType);
            if (underlyingType != null)
            {
                realModelType = underlyingType;
            }
            return realModelType;
        }

        private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

        public static string GetEnumDescription<TEnum>(TEnum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return value.ToString();
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
        {
            return EnumDropDownListFor(htmlHelper, expression, null);
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            Type enumType = GetNonNullableModelType(metadata);
            IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

            IEnumerable<SelectListItem> items = from value in values
                                                select new SelectListItem
                                                {
                                                    Text = GetEnumDescription(value),
                                                    Value = value.ToString(),
                                                    Selected = value.Equals(metadata.Model)
                                                };

            // If the enum is nullable, add an 'empty' item to the collection
            if (metadata.IsNullableValueType)
                items = SingleEmptyItem.Concat(items);

            return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
        }
    }
}
Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Nick Evans
  • 3,209
  • 2
  • 23
  • 20
  • This doesnt work, MVC 4 Razor. In the view or runtime, error = "The call is ambiguous between the following methods or properties 'LDN.Extensions.MvcExtensions.EnumDropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>)' and...." and that exact same method with same props repeated again (not enough chars allowed here). – Marc Sep 14 '12 at 22:41
9
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
Mr. Pumpkin
  • 5,427
  • 4
  • 38
  • 51
  • Good! How to get value and text from enum in this way? I mean I have SomeEnum { some1 = 1, some2 = 2} I need to get numbers (1, 2) for value and text (some1, some2) for text of selectlist – Dmitresky Mar 05 '14 at 07:59
9

You want to look at using something like Enum.GetValues

Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Garry Shutler
  • 31,001
  • 11
  • 77
  • 118
8

In .NET Core you can just use this:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
GoldenAge
  • 2,378
  • 4
  • 15
  • 46
7

This is Rune & Prise answers altered to use the Enum int value as the ID.

Sample Enum:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

Extension method:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

Sample of usage:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

Remember to Import the namespace containing the Extension method

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

Sample of generated HTML:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

Note that the item that you use to call the ToSelectList on is the selected item.

Mr. Flibble
  • 25,035
  • 21
  • 67
  • 96
6

Now this feature is supported out-of-the-box in MVC 5.1 through @Html.EnumDropDownListFor()

Check the following link:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

It is really shame that it took Microsoft 5 years to implement such as feature which is so in demand according to the voting above!

Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Lafi
  • 556
  • 4
  • 13
6

This is version for Razor:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)
user550950
  • 51
  • 1
  • 4
  • That will work only if your enum consists of contiguous values starting with 0. A Flags enum wouldn't work with this. Creative use of the indexed Select, though. – Suncat2000 Nov 21 '18 at 13:34
5

Building on Simon's answer, a similar approach is to get the Enum values to display from a Resource file, instead of in a description attribute within the Enum itself. This is helpful if your site needs to be rendered in more than one language and if you were to have a specific resource file for Enums, you could go one step further and have just Enum values, in your Enum and reference them from the extension by a convention such as [EnumName]_[EnumValue] - ultimately less typing!

The extension then looks like:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

Resources in the Enums.Resx file looking like ItemTypes_Movie : Film

One other thing I like to do is, instead of calling the extension method directly, I'd rather call it with a @Html.EditorFor(x => x.MyProperty), or ideally just have the whole form, in one neat @Html.EditorForModel(). To do this I change the string template to look like this

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

If this interests you, I've put a much more detailed answer here on my blog:

http://paulthecyclist.com/2013/05/24/enum-dropdown/

PaulTheCyclist
  • 1,097
  • 9
  • 10
5

Well I'm really late to the party, but for what it is worth, I have blogged about this very subject whereby I create a EnumHelper class that enables very easy transformation.

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

In your controller:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

In your View:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

The helper class:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}
NinjaNye
  • 6,628
  • 1
  • 30
  • 44
4

I am very late on this one but I just found a really cool way to do this with one line of code, if you are happy to add the Unconstrained Melody NuGet package (a nice, small library from Jon Skeet).

This solution is better because:

  1. It ensures (with generic type constraints) that the value really is an enum value (due to Unconstrained Melody)
  2. It avoids unnecessary boxing (due to Unconstrained Melody)
  3. It caches all the descriptions to avoid using reflection on every call (due to Unconstrained Melody)
  4. It is less code than the other solutions!

So, here are the steps to get this working:

  1. In Package Manager Console, "Install-Package UnconstrainedMelody"
  2. Add a property on your model like so:

    //Replace "YourEnum" with the type of your enum
    public IEnumerable<SelectListItem> AllItems
    {
        get
        {
            return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
        }
    }
    

Now that you have the List of SelectListItem exposed on your model, you can use the @Html.DropDownList or @Html.DropDownListFor using this property as the source.

Kolappan N
  • 2,178
  • 2
  • 26
  • 31
nootn
  • 851
  • 1
  • 11
  • 16
4

I found an answer here. However, some of my enums have [Description(...)] attribute, so I've modified the code to provide support for that:

    enum Abc
    {
        [Description("Cba")]
        Abc,

        Def
    }


    public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
    {
        IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
            .Cast<TEnum>();

        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var value in values)
        {
            string text = value.ToString();

            var member = typeof(TEnum).GetMember(value.ToString());
            if (member.Count() > 0)
            {
                var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (customAttributes.Count() > 0)
                {
                    text = ((DescriptionAttribute)customAttributes[0]).Description;
                }
            }

            items.Add(new SelectListItem
            {
                Text = text,
                Value = value.ToString(),
                Selected = (value.Equals(selectedValue))
            });
        }

        return htmlHelper.DropDownList(
            name,
            items
            );
    }

Hope that helps.

Kolappan N
  • 2,178
  • 2
  • 26
  • 31
Alkasai
  • 2,743
  • 1
  • 15
  • 25
  • I want to return a member of type = DropdownList. I am good with the Text = DescriptionAttribute but find it hard to get the int value from Value – RedBottleSanitizer Jul 16 '19 at 20:55
3
@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text="Male",Value="Male"},
 new ListItem{Text="Female",Value="Female"},
 new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)
Shahnawaz
  • 101
  • 1
  • 1
  • 4
3

Another fix to this extension method - the current version didn't select the enum's current value. I fixed the last line:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }
justabuzz
  • 792
  • 1
  • 8
  • 19
3

If you want to add localization support just change the s.toString() method to something like this:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

In here the typeof(Resources) is the resource you want to load, and then you get the localized String, also useful if your enumerator has values with multiple words.

brafales
  • 570
  • 3
  • 6
  • 22
3

This is my version of helper method. I use this:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

Instead of that:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

Here it is:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }
Vadim Sentiaev
  • 681
  • 4
  • 18
3

I would like to answer this question in a different way where, user need not to do anything in controller or Linq expression. This way...

I have a ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

Now I canto simply create a dropdown by using this enum.

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

OR

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

If you want to make a index selected then try this

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

Here I have used AccessLevelEnum.NoAccess as an extra parameter for default selecting the dropdown.

gdmanandamohon
  • 2,055
  • 18
  • 34
3

You can also use my custom HtmlHelpers in Griffin.MvcContrib. The following code:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

Generates:

enter image description here

https://github.com/jgauffin/griffin.mvccontrib

jgauffin
  • 95,399
  • 41
  • 227
  • 352
2

I ended up creating extention methods to do what is essentially the accept answer here. The last half of the Gist deals with Enum specifically.

https://gist.github.com/3813767

Nick Albrecht
  • 15,828
  • 8
  • 64
  • 95
2
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})
vicky
  • 1,389
  • 17
  • 30
  • I think this is not a valid answer, it's not using the enum at all to populate the dropdown. – Andrew Apr 30 '15 at 04:55
2

@Simon Goldstone: Thanks for your solution, it can be perfectly applied in my case. The only problem is I had to translate it to VB. But now it is done and to save other people's time (in case they need it) I put it here:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .Text = GetEnumDescription(value),
                .Value = value.ToString(),
                .Selected = value.Equals(metaData.Model)
            }

        ' If the enum is nullable, add an 'empty' item to the collection
        If metaData.IsNullableValueType Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

End You use it like this:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))
Michal B.
  • 5,497
  • 6
  • 39
  • 65
1

Here a Martin Faartoft variation where you can put custom labels which is nice for localization.

public static class EnumHtmlHelper
{
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };

        return new SelectList(values, "Id", "Name", enumObj);
    }
}

Use in view:

@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() { 
          { 1, ContactResStrings.FeedbackCategory }, 
          { 2, ContactResStrings.ComplainCategory }, 
          { 3, ContactResStrings.CommentCategory },
          { 4, ContactResStrings.OtherCategory }
      }), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)
Rushino
  • 9,055
  • 14
  • 50
  • 91
  • Are you listing each enum element in your view? What happens if you add a new element in your enum and if you have many enums for many dropdowns? – Andrew Apr 30 '15 at 04:58
1

I've done the following and works successfully:

  • In the view.cshtml:

@model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • In the Model: MyModel.cs

public ItemTypes MyItemType { get; set; }

D Mishra
  • 1,274
  • 1
  • 11
  • 17
MarwaAhmad
  • 680
  • 8
  • 20
1

In MVC4, I would do like this

@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })

public enum RefType
    {
        Web = 3,
        API = 4,
        Security = 5,
        FE = 6
    }

    public class Reference
    {
        public int Id { get; set; }
        public RefType RefType { get; set; }
    }
1
        ////  ViewModel

        public class RegisterViewModel
          {

        public RegisterViewModel()
          {
              ActionsList = new List<SelectListItem>();
          }

        public IEnumerable<SelectListItem> ActionsList { get; set; }

        public string StudentGrade { get; set; }

           }

       //// Enum Class

        public enum GradeTypes
             {
               A,
               B,
               C,
               D,
               E,
               F,
               G,
               H
            }

         ////Controller action 

           public ActionResult Student()
               {
    RegisterViewModel vm = new RegisterViewModel();
    IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
                                         .Cast<GradeTypes>();                  
    vm.ActionsList = from action in actionTypes
                     select new SelectListItem
                     {
                         Text = action.ToString(),
                         Value = action.ToString()
                     };
              return View(vm);
               }

         ////// View Action

   <div class="form-group">
                            <label class="col-lg-2 control-label" for="hobies">Student Grade:</label>
                            <div class="col-lg-10">
                               @Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
                            </div>
shuvo sarker
  • 745
  • 10
  • 19
0

1- Create your ENUM

public enum LicenseType
{
    xxx = 1,
    yyy = 2
}

2- Create your Service Class

public class LicenseTypeEnumService
    {

        public static Dictionary<int, string> GetAll()
        {

            var licenseTypes = new Dictionary<int, string>();

            licenseTypes.Add((int)LicenseType.xxx, "xxx");
            licenseTypes.Add((int)LicenseType.yyy, "yyy");

            return licenseTypes;

        }

        public static string GetById(int id)
        {

            var q = (from p in this.GetAll() where p.Key == id select p).Single();
            return q.Value;

        }

    }

3- Set the ViewBag in your controller

var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");

4- Bind your DropDownList

@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)
Mohammad Karimi
  • 3,825
  • 2
  • 19
  • 18
  • 1
    You are manually adding the enum items... If your enum changes, you have to modify your code twice. And what if you have many enums for many dropdowns? – Andrew Apr 30 '15 at 04:56
-6

UPDATED - I would suggest using the suggestion by Rune below rather than this option!


I assume that you want something like the following spat out:

<select name="blah">
    <option value="1">Movie</option>
    <option value="2">Game</option>
    <option value="3">Book</option>
</select>

which you could do with an extension method something like the following:

public static string DropdownEnum(this System.Web.Mvc.HtmlHelper helper,
                                  Enum values)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append("<select name=\"blah\">");
    string[] names = Enum.GetNames(values.GetType());
    foreach(string name in names)
    {
        sb.Append("<option value=\"");
        sb.Append(((int)Enum.Parse(values.GetType(), name)).ToString());
        sb.Append("\">");
        sb.Append(name);
        sb.Append("</option>");
    }
    sb.Append("</select>");
    return sb.ToString();
}

BUT things like this aren't localisable (i.e. it will be hard to translate into another language).

Note: you need to call the static method with an instance of the Enumeration, i.e. Html.DropdownEnum(ItemTypes.Movie);

There may be a more elegant way of doing this, but the above does work.

Ash
  • 4,741
  • 6
  • 32
  • 48
  • Thanks. That's actually the implementation I ended up with but I was hoping it was already baked into the framework. I guess not. :-( – Kevin Pang Dec 23 '08 at 22:05
  • There was something in MvcContrib for this if i remember correct. – Arnis Lapsa Oct 12 '09 at 09:07
  • I agree with your update - the solutions posted by Rune & Prise are much neater, leaving the actual markup to be rendered in the view. – belugabob Oct 12 '09 at 10:21