Click here to Skip to main content
15,895,256 members
Articles / Web Development / HTML

ASP.NET MVC: Creating localized DropDownLists for enums

Rate me:
Please Sign up or sign in to vote.
4.80/5 (12 votes)
6 Nov 2012CPOL1 min read 59.7K   1.4K   29  
A collection of HTML helpers that generate DropDownLists for enums, with or without localization support.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;

using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Resources;

using MvcEnumDropDownList.Infrastructure;

namespace MvcEnumDropDownList.Helpers
{
	/// <summary>
	/// ASP.NET MVC - Creating a DropDownList helper for enums
	/// </summary>
	/// <see cref="http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx"/>
	public static partial class DropDownList
	{
		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
		{
			return EnumDropDownListFor(htmlHelper, expression, null /* optionLabel */, null /* htmlAttributes */);
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
		{
			return EnumDropDownListFor(htmlHelper, expression, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, IDictionary<string, object> htmlAttributes)
		{
			return EnumDropDownListFor(htmlHelper, expression, null /* optionLabel */, htmlAttributes);
		}

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

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, object htmlAttributes)
		{
			return EnumDropDownListFor(htmlHelper, expression, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, IDictionary<string, object> htmlAttributes)
		{
			if(expression == null)
				throw new ArgumentNullException("expression");

			string name = GetDropDownListName(htmlHelper, expression, htmlAttributes);

			IEnumerable<SelectListItem> selectList = htmlHelper.GetSelectListItemsFor<TModel, TEnum>(expression, null);
			MvcHtmlString htmlString = htmlHelper.DropDownList(name, selectList, optionLabel, htmlAttributes);

			return htmlString;
		}



		//
		//
		// Specifying Resource type
		//
		//

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

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum, TResource>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
		{
			return EnumDropDownListFor<TModel, TEnum, TResource>(htmlHelper, expression, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum, TResource>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, IDictionary<string, object> htmlAttributes)
		{
			return EnumDropDownListFor<TModel, TEnum, TResource>(htmlHelper, expression, null /* optionLabel */, htmlAttributes);
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum, TResource>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel)
		{
			return EnumDropDownListFor<TModel, TEnum, TResource>(htmlHelper, expression, optionLabel, null /* htmlAttributes */);
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum, TResource>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, object htmlAttributes)
		{
			return EnumDropDownListFor<TModel, TEnum, TResource>(htmlHelper, expression, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
		}

		public static MvcHtmlString EnumDropDownListFor<TModel, TEnum, TResource>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, IDictionary<string, object> htmlAttributes)
		{
			if(expression == null)
				throw new ArgumentNullException("expression");

			string name = GetDropDownListName(htmlHelper, expression, htmlAttributes);

			IEnumerable<SelectListItem> selectList = htmlHelper.GetSelectListItemsFor<TModel, TEnum>(expression, typeof(TResource));
			MvcHtmlString htmlString = htmlHelper.DropDownList(name, selectList, optionLabel, htmlAttributes);

			return htmlString;
		}


		#region Private methods 

		/// <summary>
		/// Generates the name attibute value for the DropDown
		/// </summary>
		/// <typeparam name="TModel">Model type</typeparam>
		/// <typeparam name="TEnum">Enum type</typeparam>
		/// <param name="htmlHelper">HTML helper</param>
		/// <param name="expression">Model expression</param>
		/// <param name="htmlAttributes">HTML attributes</param>
		/// <returns></returns>
		public static string GetDropDownListName<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper,
			Expression<Func<TModel, TEnum>> expression, IDictionary<string, object> htmlAttributes = null)
		{
			string nameFromExpression = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));

			if(htmlAttributes == null)
				return nameFromExpression;

			// dropdownlist name:
			// if htmlAttributes["name"] exists, uses attribute 
			// if none of the previous attributes exists, uses name from lambda expression
			string name = htmlAttributes.ContainsKey("name") ?
				htmlAttributes["name"].ToString() :
				nameFromExpression;

			return name;
		}

		private static IEnumerable<SelectListItem> GetSelectListItemsFor<TModel, TEnum>(
			this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, Type resourceType)
		{
			bool isEnum = EnumHelper.IsEnum<TEnum>();

			if(!isEnum)
				throw new ArgumentException("TEnum must be an enumerated type");

			ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

			IEnumerable<SelectListItem> values = EnumHelper.GetEnumValues<TEnum>(resourceType).Select(x =>
				new SelectListItem {
					Text = x.Value,
					Value = Convert.ToInt32(x.Key).ToString(),
					Selected = x.Key.Equals(metadata.Model)
				}
			);

			return values;
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior)
Italy Italy
My name is Rui Jarimba and I was born in Madeira island, Portugal and I currently live in Rome, Italy.

I have more than 10 years of experience developing software using the .NET Framework and other technologies (Web development, Databases, ...).

Some of my professional interests are: software development best practices, software architecture, cloud computing, Continuous Integration (CI), Continuous Delivery (CD) and agile methodologies such as Scrum, Kanban, Lean and any other methodology that can help me to become a better and more productive software engineer.

I believe in good code - code that is readable, maintainable, reusable, testable and deployable. This means that I'm not the "quick and dirty" type, I write code for the medium/long term whenever possible.

Something else about me - I love music, I am an amateur photographer, not a big fan of gyms (I prefer to do some outdoor activity such as walking/hiking), big foodie (I love Mediterranean cuisine and my glass of wine!).

Comments and Discussions