Wanna bind an enum to Combobox / Dropdown ?


Many people prefer to bind an enum to a dropdown in their WinForms application. In the cases where we can not bring the values from backend/database, it makes sense to use enum as opposed to hard-coding values over and over again. Enumerations support a practice where a group of related constants may be created which later be viewed as string or integer values.

Before we see how could this be achieved in Windows Forms Application ( WinForms App ), ASP.NET WebForms, ASP.NET MVC ( even easier in MVC 5 ! ) as well as ASP.NET Web API, let’s talk about : ‘Why ?’

Why using Enum is preferred if combobox is not being flourished from DB ? Well, In addition to re-usability, there are some clear advantages :

  • In your DAL service you may declare an enum and use it throughout your solution along with data contract ( or data model )
  • They make refactoring alot easier
  • Not to mention, you’d also get intellisense in Visual Studio and avoid typos or as enums would mostly be tied to integers, string comparison might potentially be avoided.

Winforms


public enum EventDuration
{
    _30__Minutes = 30,
    _60__Minutes = 60,
    _90__Minutes = 90
}

private static void EventDurationBinder(ref ComboBox dd)
{
    dd.DataSource = Enum.GetValues(typeof(EventDuration))
                        .Cast()
                        .Select(p => new { Value = p, Text = p.ToString().Replace("__", " ").Replace("_", "") })
                        .ToList();

    dd.DisplayMember = "Text";
    dd.ValueMember = "Value";
    dd.SelectedIndex = -1;
}

Bazinga !

In the ASP.NET web development this scenario pretty much depends on which technologies are we using. For web forms this might be fairly straight forward :

Webforms


<asp:DropDownList 
    ID="ddEventDuration"
    runat="server">
</asp:DropDownList>

Let’s start from minimalistic approach, if you happen to have a simple enum of just words, name of months for example and you need to use month name strings, this approach might just work for you :


ddEventDuration.DataSource = Enum.GetNames(typeof(EventDuration));
ddEventDuration.DataBind();

But it is a very basic setup, you might need more granular control to set values different from labels, or in my case I want to get rid of the underscores I am seeing :


var dsEventDuration = Enum.GetValues(typeof(EventDuration))
						.OfType<EventDuration>()
						.Select(li => new ListItem(
							li.ToString()
								.Replace("__", " ")
								.Replace("_", "") , 
							((int)li).ToString()))
						.ToArray<ListItem>();

ddEventDuration.Items.AddRange(dsEventDuration);
ddEventDuration.DataBind();

Which gets rendered as following in your browser :


<select name="ddEventDuration" id="ddEventDuration">
	<option value="30">30 Minutes</option>
	<option value="60">60 Minutes</option>
	<option value="90">90 Minutes</option>
</select>

ASP.NET MVC

I just created a brand new MVC web app and installed ASP.NET MVC Nuget Package (Why?) Here let’s say our model has a property of type enum, I’d make up a very simple Model class below :

using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
	public class HomeModel
	{
		public int MyProperty { get; set; }
		public EventDuration Duration { get; set; }
	}

	public enum EventDuration
	{
		[Display(Name="30 Minutes")]
		_30__Minutes = 30,

		[Display(Name = "60 Minutes")]
		_60__Minutes = 60,

		[Display(Name = "90 Minutes")]
		_90__Minutes = 90
	}
}

I’d come to the use of Display attribute in a second.

If you’re on MVC 5 … ( What’s new ? )

You may simply spawn a Create.cshtml from my super awesome HomeController and then directly add following :

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

And your browser renders following !

<select id="Duration" name="Duration"><option selected="selected" value="0"></option>
	<option value="30">30 Minutes</option>
	<option value="60">60 Minutes</option>
	<option value="90">90 Minutes</option>
</select>

Bingo ! Now you know why we had Display attribute in the model šŸ˜‰

If you’re on older MVC …
@Html.DropDownListFor(o => o.Duration, 
	Enum.GetValues(typeof(WebApplication1.Models.EventDuration))
			.Cast<WebApplication1.Models.EventDuration>()
			.Select(x => new SelectListItem { 
				Text = x.ToString(), 
				Value = ((int)x).ToString() 
			}
	))

And you get this :

<select data-val="true" data-val-required="The Duration field is required." id="Duration" name="Duration">
	<option value="30">_30__Minutes</option>
	<option value="60">_60__Minutes</option>
	<option value="90">_90__Minutes</option>
</select>

Yeah, you do need to get rid of those underscores like we did above ( … or to find a better hack )

ASP.NET Web API 2

For API, we basically need to send stripped out data contract so I jot down a mini Web API controller along with a data contract class that I prefer to use in my application ( Where I need stripped out version of my object hierarchy … especially for DropDowns / Check-box list or something like that )

Here is how what I did ( just for the sake of simplicity I dumped everything at one spot )


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace WebApplication1.Controllers
{


  // Enum
  public enum EventDuration
  {
    _30__Minutes = 30,
    _60__Minutes = 60,
    _90__Minutes = 90
  }


  // Data Contract ( View Model )
  public class IdNamePairContract
  {
    public int Id { get; set; }
    public string Name { get; set; }
  }


  // Controller
  public class HomeController : ApiController
  {
    // GET api/home
    public IEnumerable<IdNamePairContract> Get()
    {
      var durations = Enum.GetValues(typeof(EventDuration))
            .OfType<EventDuration>()
            .Select(p => new IdNamePairContract { 
                Id = (int)p, 
                Name = p.ToString()
                        .Replace("__", " ")
                        .Replace("_", "") 
            })
            .AsEnumerable<IdNamePairContract>();

      return durations;
    }
  }
}

And You’d see :

Fiddler

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: foo
X-Powered-By: ASP.NET
Date: blah
Content-Length: 91

[{"Id":30,"Name":"30 Minutes"},{"Id":60,"Name":"60 Minutes"},{"Id":90,"Name":"90 Minutes"}]

Web Browser

<ArrayOfIdNamePairContract xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebApplication1.Controllers">
    <IdNamePairContract>
        <Id>30</Id>
        <Name>30 Minutes</Name>
    </IdNamePairContract>
    <IdNamePairContract>
        <Id>60</Id>
        <Name>60 Minutes</Name>
    </IdNamePairContract>
    <IdNamePairContract>
        <Id>90</Id>
        <Name>90 Minutes</Name>
    </IdNamePairContract>
</ArrayOfIdNamePairContract>

And now, in my case I’d use AngualrJS’s NgRepeat but you may use your preferred library to render the markup for your needs and preference.

//

Advertisements

Published by

Aarsh Talati

Software Developer

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s