16

I have these enums

public enum QuestionStart
{
    [Display(Name="Repeat till common match is found")]
    RepeatTillCommonIsFound,

    [Display(Name="Repeat once")]
    RepeatOnce,    

    [Display(Name="No repeat")]
    NoRepeat

}

public enum QuestionEnd
{
    [Display(Name="Cancel Invitation")]
    CancelInvitation,

    [Display(Name="Plan with participants on first available common date")]
    FirstAvailableCommon,

    [Display(Name="Plan with participants on my first available common date")]
    YourFirstAvailableCommon
}

and I have a helper class to show all the radiobutton for each field in enum

@model Enum
@foreach (var value in Enum.GetValues(Model.GetType()))
{
    @Html.RadioButtonFor(m => m, value)
    @Html.Label(value.ToString())
    <br/>
}

Right now the label is set to the value name and not the display name i have given for values.

For example for:

[Display(Name="Cancel Invitation")]
CancelInvitation

I get radio button with CancelInvitation next to it.

How can I make it display the Display name(Cancel Invitation) i have given to it?

Charles
  • 50,943
  • 13
  • 104
  • 142
Cybercop
  • 8,475
  • 21
  • 75
  • 135

4 Answers4

31

Here goes the solution -

Credit goes to this extraordinary gentleman - ThumNet, who wrote RadioButtonList for Enum as an extension

Step 1 - Create RadioButtonListEnum.cshtml file with below code (code from above reference) in Views/Shared/EditorTemplates directory (if not exist, then create that directory) -

@model Enum

@{
     // Looks for a [Display(Name="Some Name")] or a [Display(Name="Some Name", ResourceType=typeof(ResourceFile)] Attribute on your enum
    Func<Enum, string> getDescription = en =>
    {
        Type type = en.GetType();
        System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString());

        if (memInfo != null && memInfo.Length > 0)
        {

            object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute),
                                                            false);

            if (attrs != null && attrs.Length > 0)
                return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName();
        }

        return en.ToString();
    };
    var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e =>
    new SelectListItem()
    {
        Text = getDescription(e),
        Value = e.ToString(),
        Selected = e.Equals(Model)
    });
    string prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
    int index = 0;
    ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;

    foreach (var li in listItems)
    {
        string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++);
        <div class="editor-radio">
        @Html.RadioButton(prefix, li.Value, li.Selected, new { @id = fieldName }) 
        @Html.Label(fieldName, li.Text)    
        </div>
    }
    ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}

Then have your enum -

public enum QuestionEnd
{
    [Display(Name = "Cancel Invitation")]
    CancelInvitation,

    [Display(Name = "Plan with participants on first available common date")]
    FirstAvailableCommon,

    [Display(Name = "Plan with participants on my first available common date")]
    YourFirstAvailableCommon
}

Step 2 - Create Model -

public class RadioEnumModel
{
    public QuestionEnd qEnd { get; set; }
}

Step 3 - Create Controller Action -

    public ActionResult Index()
    {
        RadioEnumModel m = new RadioEnumModel();
        return View(m);
    }

Step 4 - Create View -

@model MVC.Controllers.RadioEnumModel
@Html.EditorFor(x => x.qEnd, "RadioButtonListEnum")

Then the output would be -

enter image description here

ramiramilu
  • 17,044
  • 6
  • 49
  • 66
  • seems to work. Thanks!!! Would be nice if there was inbuilt helper for these situations too, maybe in future version of MVC. But nevertheless votes up and i'll accept the answer! – Cybercop Feb 10 '14 at 14:56
  • 1+ for your effort :) – Syed Ali Jan 12 '17 at 11:34
2

I found some of these answers confusing, this is how I ended up achieving the result. Hopefully this helps someone else.

Shove this in an extension methods file:

public static string GetDescription(this Enum value)
{
    Type type = value.GetType();
    string name = Enum.GetName(type, value);
    if (name != null)
    {
        FieldInfo field = type.GetField(name);
        if (field != null)
        {
            DescriptionAttribute attr =
                   Attribute.GetCustomAttribute(field,
                     typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attr != null)
            {
                return attr.Description;
            }
        }
    }
    return null;
}

Make sure you add a property that is the same type as your enum to your actual Model so that the radio button selection binds.

Create an editor template for your particular enum. Then in your view reference it like so:

@Html.EditorFor(m => m.MyEnumTypePropertyName)

Then add the following to your EditorTemplate:

@using MyProject.ExtensionMethods;
@model MyProject.Models.Enums.MyEnumType

    @foreach (MyEnumType value in Enum.GetValues(typeof(MyEnumType)))
    {
        <div>
            @Html.Label(value.GetDescription())
            @Html.RadioButtonFor(m => m, value)
        </div>
    }

Remember - If you don't select a radio button for whatever reason, the default value for your enum property when posted will always be the first in the pack (i.e. zero), not null.

JsonStatham
  • 9,770
  • 27
  • 100
  • 181
0

You can use the following overload method.

@Html.Label(value.ToString(),"Cancel Invitation")

This will render the label with specified labeltext provided as second parameter in above call.

Ishtiaq
  • 980
  • 2
  • 6
  • 21
0

Here is a solution that uses an extension method and an editor template to create a radio group with a localized name from the display attribute.

Extension Method

public static string DisplayName(this Enum enumValue)
{
    var enumType = enumValue.GetType();
    var memberInfo = enumType.GetMember(enumValue.ToString()).First();

    if (memberInfo == null || !memberInfo.CustomAttributes.Any()) return enumValue.ToString();

    var displayAttribute = memberInfo.GetCustomAttribute<DisplayAttribute>();

    if (displayAttribute == null) return enumValue.ToString();

    if (displayAttribute.ResourceType != null && displayAttribute.Name != null)
    {
        var manager = new ResourceManager(displayAttribute.ResourceType);
        return manager.GetString(displayAttribute.Name);
    }

    return displayAttribute.Name ?? enumValue.ToString();
}

Example

public enum IndexGroupBy 
{
    [Display(Name = "By Alpha")]
    ByAlpha,
    [Display(Name = "By Type")]
    ByType
}

And here is its usage:

@IndexGroupBy.ByAlpha.DisplayName()

Editor Template

Here is an editor template that can be used with the extension method above:

@model Enum

@{    
    var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e =>
        new SelectListItem
        {
            Text = e.DisplayName(),
            Value = e.ToString(),
            Selected = e.Equals(Model)
        });
    var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
    var index = 0;
    ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;

    foreach (var li in listItems)
    {
        var fieldName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++);
        <div class="editor-radio">
            @Html.RadioButton(prefix, li.Value, li.Selected, new {@id = fieldName})
            @Html.Label(fieldName, li.Text)
        </div>
    }
    ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}

And here is an example usage:

@Html.EditorFor(m => m.YourEnumMember, "Enum_RadioButtonList")
Mark Good
  • 4,271
  • 2
  • 31
  • 43