5

I need to display the name of the enum for corresponding value inside DisplayFor HtmlHelper. I have the following enum:

public enum CheckStatus
    {
        Yes = 1,
        No = 2,
        Maybe =3
    }

I'm displaying values for a model normally like this:

@Html.DisplayFor(modelItem => item.Name)

The problem is that at one point I have this:

@Html.DisplayFor(modelItem => item.Status)

That line displays only status value which is set before from enum (1,2 or 3). Instead of that I need somehow to display name for that value. So, if status code is 2, I want to display 'No', not number 2.

I had the similar problem with getting enum names when I was populating dropdown list and I managed to solve it like this:

@Html.DropDownListFor(model => model.Item.Status,
                new SelectList(Enum.GetValues(typeof(Pro.Web.Models.Enums.CheckStatus))))

I am a little bit lost in how to get only that one name from the value of the enum.

Thank you for your help.

Cristiano
  • 3,099
  • 10
  • 45
  • 67

4 Answers4

7

It's not very clear from your question what's the underlying type of the Status property. If it is CheckStatus, then @Html.DisplayFor(modelItem => item.Status) will display exactly what you expect. If on the other hand it is an integer you could write a custom helper to display the proper value:

public static class HtmlExtensions
{
    public static IHtmlString DisplayEnumFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, int>> ex, Type enumType)
    {
        var value = (int)ModelMetadata.FromLambdaExpression(ex, html.ViewData).Model;
        string enumValue = Enum.GetName(enumType, value);
        return new HtmlString(html.Encode(enumValue));
    }
}

and then use it like this:

@Html.DisplayEnumFor(modelItem => item.Status, typeof(CheckStatus))

and let's suppose that you wanted to bring this helper a step further and take into account the DisplayName attribute on your enum type:

public enum CheckStatus
{
    [Display(Name = "oh yeah")]
    Yes = 1,
    [Display(Name = "no, no, no...")]
    No = 2,
    [Display(Name = "well, dunno")]
    Maybe = 3
}

Here's how you could extend our custom helper:

public static class HtmlExtensions
{
    public static IHtmlString DisplayEnumFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, int>> ex, Type enumType)
    {
        var value = (int)ModelMetadata.FromLambdaExpression(ex, html.ViewData).Model;
        string enumValue = Enum.GetName(enumType, value);
        var field = enumType.GetField(enumValue);
        if (field != null)
        {
            var displayAttribute = field
                .GetCustomAttributes(typeof(DisplayAttribute), false)
                .Cast<DisplayAttribute>()
                .FirstOrDefault();
            if (displayAttribute != null)
            {
                return new HtmlString(html.Encode(displayAttribute.Name));
            }
        }
        return new HtmlString(html.Encode(enumValue));
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Status is integer. Status can only have numbers 1,2 and 3. Thank you for this suggestion. Where should I put this helper class? In some separate new Helper directory in project root and then reference it in view with @using or? – Cristiano Mar 31 '13 at 15:56
  • You could create a `Helpers` folder under the root of your project and define the extension method there. Also in order for this extension method ot be visible in your view you need to bring the namespace in which the static class is defined into scope. This could be done by adding this namespace to the `` section in `~/Views/web.config` (not to confuse with `~/web.config`). – Darin Dimitrov Mar 31 '13 at 15:56
  • Your code is more risky .Please see my new answer. Its return enum name correctly. int enumvalue=(int)(YourModel.Status)// this property must be integer value only var checkStatusName= Enum.GetName(typeof(CheckStatus), enumvalue); – Ramesh Rajendran Mar 31 '13 at 16:14
  • I don't see how my code is any riskier than yours. In both cases the value must be an integer in order for the code to work. In fact my code is a little more general than yours because it will also work with short types which are possible values for an enum, whereas in your code you are casting to Int32. – Darin Dimitrov Mar 31 '13 at 16:16
  • I'm trying this version currently, then I will try other :) @DarinDimitrov - I put `` inside `~/Views/web.config` and I'm still getting a warning there is no definition for `DisplayEnumFor`. – Cristiano Mar 31 '13 at 16:36
  • You need to close and reopen the Razor view in order for the changes to take effect. Razor Intellisense in Visual Studio sucks badly. Trust your code and run the application. You will see that it works. Never trust the warnings you get in a Razor view. – Darin Dimitrov Mar 31 '13 at 16:37
  • I tried to Clean and Rebuild and nothing removed errors but after I restarted Visual Studio warnings disappeared. Thanks! – Cristiano Mar 31 '13 at 16:47
  • btw, better to use `DisplayAttribute.GetName()` - its localizable – lxa Mar 19 '15 at 20:08
3

Edit:

You can simply try this way. please try my below code in your controller class

controller:

int enumvalue=(int)(YourModel.Status)// this property must be integer value only
var checkStatusName= Enum.GetName(typeof(CheckStatus), enumvalue);
Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
1

Adapted @DarinDimitrov code as display template.

If you have

public enum CheckStatus
{
    [Display(Name = "oh yeah")]
    Yes = 1,
    [Display(Name = "no, no, no...")]
    No = 2,
    [Display(Name = "well, dunno")]
    Maybe = 3
}

public class MyModel
{
    public CheckStatus Status { get; set; }
}

put following into Views/DisplayTemplates/Enum.cshtml :

@using System.ComponentModel.DataAnnotations
@model object

@{
    var value = Model.ToString();
    var field = Model.GetType().GetField(value);
    if (field != null)
    {
        var displayAttribute = field
                .GetCustomAttributes(typeof(DisplayAttribute), false)
                .Cast<DisplayAttribute>()
                .FirstOrDefault();

        if (displayAttribute != null)
        {
            value = displayAttribute.GetName();
        }
    }
}

@value

and now you can simply write in your view:

@Html.DisplayFor(model => model.Status)
lxa
  • 3,234
  • 2
  • 30
  • 31
1

using razor/MVC you can get this for "free" if your property in not declared as an int type but rather as the enum type yoou are using.

The problem I have with Darin solution is although it works for me if I use the int type, I could not get the look of my other fields @Html.EditorFor(...) in the view.

Patrick R
  • 31
  • 4