Creating user friendly strings for enum values

In this post, I’ll show you how to create a custom attribute for enum values to assign extra information to an enum. In this case, we’ll be associating a user friendly display name.

Order Status Screenshot

In .NET, enums are basically a list of constant values. It’s a way to assign code friendly names to a group of values. For example, an order status:

enum OrderStatus
{
	NewOrder = 1,
	Processing = 2,
	Shipped = 3
}

In the above example, the numeric values are optional, they will be assigned automatically if you don’t supply them.

What if you want to display the enum values in a drop down list, so that an admin can change the status of an order? One option is to loop through the enum, and display the code value ("NewOrder, "Processing", etc.). Another option is to have a "switch" statement or a "for" statement that allows you to hard code a user friendly value.

Another option is to create a custom attribute to add additional meta data:

public class EnumValueDataAttribute : Attribute
{
	private string _name;
	public string Name
	{
		get{ return _name; }
		set{ _name = value; }
	}
}

Now we can use the attribute to the enum I showed you previously:

enum OrderStatus
{
	[EnumValueData(Name="New Order")]
	NewOrder = 1,
	[EnumValueData(Name="In Process")]
	Processing = 2,
	[EnumValueData(Name="Shipped")]
	Shipped = 3
}

Now we can create a method that gets the data in a useful format:

public static Dictionary<int, string> GetListItems(Type enumType)
{
	if (!enumType.IsEnum)
		throw new ApplicationException("GetListItems does not support non-enum types");
	Dictionary<int, string> list = new Dictionary<int, string>();
	foreach(FieldInfo field in enumType.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public))
	{
		int value;
		string display;
		value = (int)field.GetValue(null);
		display = Enum.GetName(enumType, value);
		foreach(Attribute currAttr in field.GetCustomAttributes(true))
		{
			EnumValueDataAttribute valueAttribute = currAttr as EnumValueDataAttribute;
			if (valueAttribute != null)
				display = valueAttribute.Name;
		}
		list.Add(value, display);
	}
	return list;
}

Notice that the method will also work even if the "EnumValueData" attribute is missing, so you don’t have to supply it for every value.

Based off of this code, you could easily create additional fields to associate with enum values. Basically what we’re doing is creating a simple database table in our code. You’ll have to decide if this is a good idea for your project.

Kick It!

11 Comments so far »

  1. Moggoly said,

    Wrote on May 1, 2008 @ 7:40 am

    There is a much simpler way of getting descriptive values from Enum values using framework attributes as I’ve described here:

    http://www.moggoly.me.uk/blog/post/Enum-description-values.aspx

  2. Dan Rigsby said,

    Wrote on May 1, 2008 @ 10:36 am

    What about localizing these strings? Names are usually best kept in resource files for these reasons. What might be better is to add a value for a key in a resource file as well the default name value you have defined. If there is no resource file or no item for that key, then it can display the default name.

  3. Eber Irigoyen said,

    Wrote on May 1, 2008 @ 6:12 pm

    I prefere the much simpler approach of storing the strings in the resources, which solves localization at the same time

  4. Nathan Baulch said,

    Wrote on May 1, 2008 @ 7:22 pm

    Or even better, use a TypeConverter so that it transparently works with databinding:
    http://www.codeproject.com/KB/dotnet/DotNetEnumsNextLevel.aspx?msg=1604037#xx1604037xx

  5. Shafqat Ahmed said,

    Wrote on May 2, 2008 @ 3:52 am

    Why go through all the trouble?

    Use reflection to populate the list …
    Also for nice Spaced words write a string function that finds the upper case words and adds a space … like … “CoolComment” become “Cool Comment”. Why add the attributes, another hassle.

    Also name your enums in a way that they come as nice words

  6. Aaron Zalewski said,

    Wrote on May 2, 2008 @ 7:32 am

    Good post, I’ve been using enums most extensively to store the output ColumnNames of returned data.

    RE: formatting
    One option might be to use an underscore to seperate “words” and do a simple .Replace(”_”,” “) when the displayed version of the enum is required. That way upper/lower case doesn’t play into formatting.

  7. superjason said,

    Wrote on May 2, 2008 @ 8:40 am

    Lots of great ideas. That’s why I love posting stuff like this!

  8. Tim said,

    Wrote on May 2, 2008 @ 10:24 am

  9. Jeff said,

    Wrote on May 2, 2008 @ 11:34 am

    An atttibute similar to this exists in the framework: System.Xml.Serialization.XmlEnumAttribute. To use it, it’s almost the same as your suggestion:

    [System.SerializableAttribute()]
    public enum TestEnum
    {
    value1,

    [System.Xml.Serialization.XmlEnumAttribute("hi")]
    value2
    }

    Then in code:

    public static string ToStringUsingXmlEnumAttribute( Enum value )
    {
    if ( value == null ) throw new ArgumentNullException( “value” );

    XmlEnumAttribute[ ] attribs = (XmlEnumAttribute[ ])value.GetType( ).GetField( value.ToString( ) ).GetCustomAttributes( typeof( XmlEnumAttribute ), true );

    return ( attribs.Length > 0 ) ? attribs[ 0 ].Name : value.ToString( );
    }

  10. Your Teacher said,

    Wrote on May 2, 2008 @ 3:20 pm

    > I think logically.

    Oh LOL, this entry is making me laugh my socks off.

    Go on Son, reflect the mirror..

  11. Naz said,

    Wrote on June 3, 2008 @ 11:38 am

    I’ve done this using extension methods you can check it out here.

    http://www.objectreference.net/post/enum-to-friendly-string-extension-method.aspx

Comment RSS · TrackBack URI

Leave a Comment

Name: (Required)

E-mail: (Required)

Website:

Comment: