Click here to Skip to main content
15,881,687 members
Articles / Programming Languages / C#

MVC Enum RadioButtonList Helper

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
14 Jun 2012CPOL 53.5K   11   9
An MVC Razor Helper to generate radio button lists from enums

Introduction

I came across a problem where I would like to use a Radio Button List for selecting an Enumeration value. I found a nice little example online by Jon Lanceley here but found it to be missing a couple of features. So... as all developers do, we tinker and add.

The Code

I'll include both sets of code so that you can see the difference. 

Here is the original block of code that Jon published.  

C#
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 
using System.Linq.Expressions; 
using System.Text;
namespace MVC3_RadioButtonList_Helper_Sample 
{ 
    public static class HtmlExtensions 
    { 
        public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>( 
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            IEnumerable<SelectListItem> listOfValues) 
        { 
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
            var sb = new StringBuilder();
            if (listOfValues != null) 
            { 
                // Create a radio button for each item in the list 
                foreach (SelectListItem item in listOfValues) 
                { 
                    // Generate an id to be given to the radio button field 
                    var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);
                    // Create and populate a radio button using the existing html helpers 
                    var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text)); 
                    var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();
                    // Create the html string that will be returned to the client 
                    // e.g. <input data-val="true" data-val-required=
                    //   "You must select an option" id="TestRadio_1" 
                    //   name="TestRadio" type="radio" 
                    //   value="1" /><label for="TestRadio_1">Line1</label> 
                    sb.AppendFormat("<div class=\"RadioButton\">{0}{1}</div>", radio, label); 
                } 
            }
            return MvcHtmlString.Create(sb.ToString()); 
        } 
    } 
}

And here is my updated code. 

C#
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 
using System.Linq.Expressions; 
using System.Text;

namespace MVC3_RadioButtonList_Helper_Sample 
{ 
    public static class HtmlExtensions 
    { 
        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();
        }

        public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<SelectListItem> listOfValues, Position position = Position.Horizontal)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            string fullName = ExpressionHelper.GetExpressionText(expression);
            var sb = new StringBuilder();

            if (listOfValues != null)
            {
                // Create a radio button for each item in the list 
                foreach (SelectListItem item in listOfValues)
                {
                    // Generate an id to be given to the radio button field 
                    var id = string.Format("rb_{0}_{1}", 
                      fullName.Replace("[", "").Replace(
                      "]", "").Replace(".", "_"), item.Value);
                    
                    // Create and populate a radio button using the existing html helpers 
                    var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
                    //var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();
                    var radio = htmlHelper.RadioButton(fullName, item.Value, item.Selected, new { id = id }).ToHtmlString();

                    // Create the html string that will be returned to the client 
                    // e.g. <input data-val="true" data-val-required=
                    //   "You must select an option" id="TestRadio_1" 
                    /    name="TestRadio" type="radio"
                    //   value="1" /><label for="TestRadio_1">Line1</label> 
                    sb.AppendFormat("<{2} class=\"RadioButton\">{0}{1}</{2}>", 
                       radio, label, (position == Position.Horizontal ? "span" : "div"));
                }
            }

            return MvcHtmlString.Create(sb.ToString());
        } 
    }
}

The differences 

His code was pretty good but missed a couple of things. The first was an easy way to generate the actual list of items. The second was that he didn't account for models that contained an indexer in its parentage. Using the helper methods fixes the first one and using the same method Microsoft uses to find the full name of the property fixes the second. Adding the "rb_" to the front of the id's ensures that the id name is always legal. 

Hope this is helpful and thanks to Jon for a pretty good helper method to start from. 

History

Initial publication.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Stackify
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionDoesn't Compile Pin
syqosis25-Mar-15 23:42
syqosis25-Mar-15 23:42 
AnswerRe: Doesn't Compile Pin
Daniel Gidman27-Mar-15 15:13
professionalDaniel Gidman27-Mar-15 15:13 
GeneralImprovements Pin
Hal Diggs5-Dec-14 16:14
professionalHal Diggs5-Dec-14 16:14 
GeneralRe: Improvements Pin
Daniel Gidman27-Mar-15 15:11
professionalDaniel Gidman27-Mar-15 15:11 
QuestionMVC4 Pin
GregoryW12-Sep-13 8:58
GregoryW12-Sep-13 8:58 
I did a test @MVC4, works without any problems! Thanks.
286 => 486 DX 100MHz => Pentium P75 => AMD K6-300 => AMD Duron 1GHz => Smile | :)
Pascal => PHP3 => JavaScript => C => C++ => C# => VB.NET => Smile | :)


modified 12-Sep-13 15:07pm.

QuestionRadioButtonList Pin
dara ammar26-Jul-13 21:17
dara ammar26-Jul-13 21:17 
QuestionMVC Enum RadioButtonList Helper Pin
DanCooley27-Jun-12 10:28
DanCooley27-Jun-12 10:28 
AnswerRe: MVC Enum RadioButtonList Helper Pin
Daniel Gidman27-Jun-12 11:15
professionalDaniel Gidman27-Jun-12 11:15 
Questionnot an article.. Pin
Seishin#14-Jun-12 19:35
Seishin#14-Jun-12 19:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.