Click here to Skip to main content
15,885,978 members
Articles / Programming Languages / C#
Article

Enums in C#

Rate me:
Please Sign up or sign in to vote.
2.27/5 (7 votes)
10 Aug 2010CPOL3 min read 33.1K   213   8   6
Mapping enum constants with user friendly names.

Introduction

An enum is a distinct type consisting of a set of named constants. A very useful feature when we are definite about all the values that a variable can have (for example, control alignment). We can use an enum and define all possible values for it. And when we use it within code, we have named constants, very clean and safe. Sometimes we need to show the value of a variable of some enum type to the user. It's very easy to do that using the ToString() function. But sometimes, we have constants defined for our enums that do not go very well with usability testing. Consider the enum below:

C#
public enum AlignmentEnum
{
    TopLeft,
    TopRight,
    TopCenter,
    CenterCenter,
    BottomRight,
    BottomLeft,
    BottomCenter
}

When these constants are displayed to the user (say, on a form), they would appear as is. TopLeft.ToString() would return "TopLeft" and so on. Those constants look pretty straightforward to read and understand to most of us. But they are sure to find place in usability testing notes. Your tester is going to tell you that TopLeft should be displayed as "Top of Left" and that what could the user possibly make out of CenterCenter?! Now, I agree that sometimes developers do get a little emotional with their naming habits, but they have their own way of understanding them! So what is the solution?

Proposed Solution

It would be wonderful if we could somehow just map these constants with some user friendly names. Wherever we need to display an enum, the user friendly value would be displayed, and whenever we need to use the constant, the actual enum would be available. This could be a solution that can handle the usability tests and the strange naming habits of my developer brothers.

The Solution

Image 1

This is a simple solution. We create a custom attribute class that has a couple of properties to describe a constant from an enum. And then we use it to decorate our enum with attributes describing each one of the constants. There goes our mapping of enum constants with user-friendly names. And to create an item source out of the list of these attributes (so that we can use it in our ListBox or anywhere we want to display the enum constants), we use a class derived from TypeDelegator. Here, ObjectDataProvider helps us in XAML to create the required enumerator from the GetCustomAttributes function of the TypeDelegator class.

Explaining the Solution

The solution is made out of three parts. We use custom attributes to describe each one of the enum constants' user friendly names (DescriptionAttribute class in the project).

C#
/// <summary>
/// When applied to an Enum (one entry for each one of the member elements),
/// allows user to enter meta information that can be later accessed
/// </summary>
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class DescriptionAttribute : Attribute
{

    private System.String mDescription;    
    /// <summary>
    /// Gets the user friendly description 
    //  of the Enum that will be displayed to the user
    /// </summary>
    public System.String Description
    {
        get
        {
            return mDescription;
        }
        private set
        {
            mDescription = value;
        }
    }

    private System.Object mEnumConstant;
    /// <summary>
    /// Gets the Enum member, for which description is required
    /// </summary>
    public System.Object EnumConstant
    {
        get
        {
            return mEnumConstant;
        }
        private set
        {
            mEnumConstant = value;
        }
    }
    /// <summary>
    /// Initializes a User firendly metadata for each one of the memebers of the Enum
    /// </summary>
    /// <param name="en">The Enum member for which
    /// a user friendly description is required</param>
    /// <param name="description">User friendly description
    /// for the specified member of the Enum</param>
    public DescriptionAttribute(System.Object en, System.String description)
    {
        mEnumConstant = en;
        mDescription = description;
    }
}

The class has a property called EnumConstant to be used to store the constant from the enum for which we need a user friendly name. And then we have a Description property that has the user friendly name for the constant in question. The DescriptionAttribute is used to attribute the enum for each one of its constants. Decorating the enum using DescriptionAttribute would be simple.

C#
[UserFriendlyEnums.Description(AlignmentEnum.BottomRight, "Bottom of right")]
[UserFriendlyEnums.Description(AlignmentEnum.TopCenter, "Center top")]
[UserFriendlyEnums.Description(AlignmentEnum.BottomCenter, "Center bottom")]
[UserFriendlyEnums.Description(AlignmentEnum.CenterCenter, "Center")]
[UserFriendlyEnums.Description(AlignmentEnum.BottomLeft, "Bottom of left")]
[UserFriendlyEnums.Description(AlignmentEnum.TopLeft, "Top of left")]
[UserFriendlyEnums.Description(AlignmentEnum.TopRight, "Top of right")]
public enum AlignmentEnum
{
    TopLeft,
    TopRight,
    TopCenter,
    CenterCenter,
    BottomRight,
    BottomLeft,
    BottomCenter
}

For every enum constant, we place an attribute on top of the enum.

We use a generic class derived from 'TypeDelegator' for its 'GetCustomAttributes' function (the XamlableTypeDelegator class in the project). We create a derived class because TypeDelegator cannot be used in XAML directly.

C#
/// <summary>
/// A basic type derived from System.Reflection.TypeDelegator
/// </summary>
public class XamlableTypeDelegator:System.Reflection.TypeDelegator
{
    /// <summary>
    /// Initializes the type derived from TypeDelegator that can be initialized in Xaml
    /// </summary>
    /// <param name="delegatingType">The type that is the delegating
    /// type of the base TypeDelegator</param>
    public XamlableTypeDelegator(Type delegatingType) :
        base(delegatingType) { }
}

And finally, we use ObjectDataProvider to create an instance of the aforesaid generic class to create an item source from the GetCustomAttributes function (the resource with the name 'UserFriendlyEnumProvider' that is actually a ObjectDataProvider object).

XML
<ObjectDataProvider MethodName="GetCustomAttributes" 
                    ObjectType="{x:Type this:XamlableTypeDelegator}" 
                    x:Key="UserFriendlyEnumProvider" >
    <ObjectDataProvider.ConstructorParameters>
        <x:Type TypeName="this:AlignmentEnum"/>
    </ObjectDataProvider.ConstructorParameters>
    <ObjectDataProvider.MethodParameters>
        <sys:Boolean>false</sys:Boolean>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

This is the final step of our solution, where we finally ready with a list of DescriptionAttribute objects, one each for all the constants of an enum. We can use it as an item source for any control exposing this property. In the demo application, we also use CollectionViewSource to sort the list of enum constants.

License

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


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

Comments and Discussions

 
GeneralMy vote of 2 Pin
Bernhard Hiller19-Aug-10 21:08
Bernhard Hiller19-Aug-10 21:08 
GeneralEnumDescConverter Pin
Bernhard Hiller19-Aug-10 21:06
Bernhard Hiller19-Aug-10 21:06 
GeneralMy vote of 1 Pin
voloda211-Aug-10 23:25
voloda211-Aug-10 23:25 
GeneralMy vote of 1 Pin
Jay Riggs10-Aug-10 11:00
Jay Riggs10-Aug-10 11:00 
GeneralNeedlessly reinventing a wheel Pin
PIEBALDconsult10-Aug-10 8:07
mvePIEBALDconsult10-Aug-10 8:07 
GeneralMy vote of 2 Pin
Toli Cuturicu10-Aug-10 6:00
Toli Cuturicu10-Aug-10 6:00 
There are already a lot of (better) articles addressing this issue. You don't do anything new here.

modified on Tuesday, August 10, 2010 3:21 PM

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.