Click here to Skip to main content
11,412,833 members (75,517 online)
Click here to Skip to main content

Tagged as

Enums in C#

, 10 Aug 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

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

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).

/// <span class="code-SummaryComment"><summary>
</span>/// 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
/// <span class="code-SummaryComment"></summary>
</span>[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class DescriptionAttribute : Attribute
{

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

    private System.Object mEnumConstant;
    /// <span class="code-SummaryComment"><summary>
</span>    /// Gets the Enum member, for which description is required
    /// <span class="code-SummaryComment"></summary>
</span>    public System.Object EnumConstant
    {
        get
        {
            return mEnumConstant;
        }
        private set
        {
            mEnumConstant = value;
        }
    }
    /// <span class="code-SummaryComment"><summary>
</span>    /// Initializes a User firendly metadata for each one of the memebers of the Enum
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="en">The Enum member for which
</span>    /// a user friendly description is required<span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><param name="description">User friendly description
</span>    /// for the specified member of the Enum<span class="code-SummaryComment"></param>
</span>    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.

[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.

/// <span class="code-SummaryComment"><summary>
</span>/// A basic type derived from System.Reflection.TypeDelegator
/// <span class="code-SummaryComment"></summary>
</span>public class XamlableTypeDelegator:System.Reflection.TypeDelegator
{
    /// <span class="code-SummaryComment"><summary>
</span>    /// Initializes the type derived from TypeDelegator that can be initialized in Xaml
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="delegatingType">The type that is the delegating
</span>    /// type of the base TypeDelegator<span class="code-SummaryComment"></param>
</span>    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).

<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)

Share

About the Author

VermaManish

India India
No Biography provided

Comments and Discussions

 
GeneralMy vote of 2 Pin
bhiller at 19-Aug-10 22:08
memberbhiller19-Aug-10 22:08 
GeneralEnumDescConverter Pin
bhiller at 19-Aug-10 22:06
memberbhiller19-Aug-10 22:06 
GeneralMy vote of 1 Pin
voloda2 at 12-Aug-10 0:25
membervoloda212-Aug-10 0:25 
GeneralMy vote of 1 Pin
JRiggs at 10-Aug-10 12:00
memberJRiggs10-Aug-10 12:00 
GeneralNeedlessly reinventing a wheel Pin
PIEBALDconsult at 10-Aug-10 9:07
mvpPIEBALDconsult10-Aug-10 9:07 
GeneralMy vote of 2 Pin
Toli Cuturicu at 10-Aug-10 7:00
memberToli Cuturicu10-Aug-10 7:00 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150427.1 | Last Updated 10 Aug 2010
Article Copyright 2010 by VermaManish
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid