Results 1 to 2 of 2

Thread: [.NET 2.0+] Displaying Friendly Names for Enumerations

  1. #1

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    [.NET 2.0+] Displaying Friendly Names for Enumerations

    VB version here.

    I've seen information on this technique in several places, possibly even on this forum. I've extended what I've read by creating a couple of classes that make displaying friendly names easier.

    First, a bit of background. Enumerations, created in C# with the 'enum' key word, are lists of text values that each correspond to a number. They are used to provide a limited list of possible values. We use them in many situations, for instance the DialogResult values that are returned by MessageBox.Show are members of the DialogResult enumeration. The idea is that the text labels are descriptive and make life easier for the developer, while the system uses the underlying numeric values for speed and efficiency. Enumerations are better than either String or Integer when you want to limit the possible choices a variable can take.

    I say that the text labels are friendly to the developer, but what about the user? The text labels used for enumerated constants must obey the same rules as other identifiers. That means that they must start with a letter or an underscore and can only contain letters, numbers and underscores. They cannot contain spaces or punctuation. That makes them a little less friendly to display to the user in the UI. It would be nice if we could associate a standard String with each value and display those to the user. Well, we can do that, using the DescriptionAttribute class:
    CSharp Code:
    1. using System.ComponentModel;
    2.  
    3. public enum TestEnum
    4. {
    5.     [Description("This is the first value")]
    6.     FirstValue,
    7.     [Description("Hello from the second value")]
    8.     SecondValue,
    9.     [Description("Third value here")]
    10.     ThirdValue
    11. }
    Note the spaces in the descriptions that are not allowed in the value names themselves. Now, the question is, how do we actually get those descriptions in code? The answer is to use reflection. In other places I've seen this done with a method at the form level or the like. I've been a good little OOPer and created a couple of classes to do the job. The following EnumDescriptor class encapsulates the reflection code, providing access to an enumerated value and its description via properties:
    CSharp Code:
    1. using System.ComponentModel;
    2. using System.Reflection;
    3.  
    4. /// <summary>
    5. /// Contains an enumerated constant value and a friendly description of that value, if one exists.
    6. /// </summary>
    7. /// <typeparam name="T">
    8. /// The enumerated type of the value.
    9. /// </typeparam>
    10. public class EnumDescriptor<T>
    11. {
    12.     /// <summary>
    13.     /// The friendly description of the value.
    14.     /// </summary>
    15.     private string _description;
    16.     /// <summary>
    17.     /// The enumerated constant value.
    18.     /// </summary>
    19.     private T _value;
    20.  
    21.     /// <summary>
    22.     /// Gets the friendly description of the value.
    23.     /// </summary>
    24.     /// <value>
    25.     /// A <b>String</b> containing the value's Description attribute value if one exists; otherwise, the value name.
    26.     /// </value>
    27.     public string Description
    28.     {
    29.         get
    30.         {
    31.             return this._description;
    32.         }
    33.         set
    34.         {
    35.             this._description = value;
    36.         }
    37.     }
    38.  
    39.     /// <summary>
    40.     /// Gets the enumerated constant value.
    41.     /// </summary>
    42.     /// <value>
    43.     /// An enumerated constant of the <b>EnumDescriptor's</b> generic parameter type.
    44.     /// </value>
    45.     public T Value
    46.     {
    47.         get
    48.         {
    49.             return this._value;
    50.         }
    51.         set
    52.         {
    53.             this._value = value;
    54.         }
    55.     }
    56.  
    57.     /// <summary>
    58.     /// Creates a new instance of the <b>EnumDescriptor</b> class.
    59.     /// </summary>
    60.     /// <param name="value">
    61.     /// The value to provide a description for.
    62.     /// </param>
    63.     public EnumDescriptor(T value)
    64.     {
    65.         this._value = value;
    66.  
    67.         // Get the Description attribute.
    68.         FieldInfo field = value.GetType().GetField(value.ToString());
    69.         DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute),
    70.                                                                                               false);
    71.  
    72.         // Use the Description attribte if one exists, otherwise use the value itself as the description.
    73.         this._description = attributes.Length == 0 ? value.ToString()
    74.                                                    : attributes[0].Description;
    75.     }
    76.  
    77.     /// <summary>
    78.     /// Overridden.  Creates a string representation of the object.
    79.     /// </summary>
    80.     /// <returns>
    81.     /// The friendly description of the value.
    82.     /// </returns>
    83.     public override string ToString()
    84.     {
    85.         return this._description;
    86.     }
    87. }
    I've also created a class to automatically create an EnumDescriptor for each member of an enumeration and store them as a collection:
    CSharp Code:
    1. using System;
    2.  
    3. /// <summary>
    4. /// A collection of EnumDescriptors for an enumerated type.
    5. /// </summary>
    6. /// <typeparam name="T">
    7. /// The type of the enumeration for which the EnumDescriptors are created.
    8. /// </typeparam>
    9. public class EnumDescriptorCollection<T> : System.Collections.ObjectModel.Collection<EnumDescriptor<T>>
    10. {
    11.     /// <summary>
    12.     /// Creates a new instance of the <b>EnumDescriptorCollection</b> class.
    13.     /// </summary>
    14.     public EnumDescriptorCollection()
    15.     {
    16.         // Populate the collection with an EnumDescriptor for each enumerated value.
    17.         foreach (T value in Enum.GetValues(typeof(T)))
    18.         {
    19.             this.Items.Add(new EnumDescriptor<T>(value));
    20.         }
    21.     }
    22. }
    An example of how you might use these classes is:
    CSharp Code:
    1. private void Form1_Load(object sender, EventArgs e)
    2. {
    3.     this.comboBox1.DisplayMember = "Description";
    4.     this.comboBox1.ValueMember = "Value";
    5.     this.comboBox1.DataSource = new EnumDescriptorCollection<TestEnum>();
    6. }
    7.  
    8. private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    9. {
    10.     MessageBox.Show(this.comboBox1.SelectedValue.ToString(), this.comboBox1.Text);
    11. }
    So, there's no need for you to mess around each time you want to do this once you have these classes. It's one line to create a collection containing the enumerated values and their descriptions, which you can bind or use however you like.

    I've attached code files for the EnumDescriptor and EnumDescriptorCollection classes.
    Attached Files Attached Files

  2. #2

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: [.NET 2.0+] Displaying Friendly Names for Enumerations

    Here's a more succinct version of the EnumDescriptor class for more recent versions of C#:
    csharp Code:
    1. using System.ComponentModel;
    2. using System.Linq;
    3.  
    4. /// <summary>
    5. /// Contains an enumerated constant value and a friendly description of that value, if one exists.
    6. /// </summary>
    7. /// <typeparam name="T">
    8. /// The enumerated type of the value.
    9. /// </typeparam>
    10. public class EnumDescriptor<T>
    11. {
    12.     /// <summary>
    13.     /// Gets the friendly description of the value.
    14.     /// </summary>
    15.     /// <value>
    16.     /// A <b>String</b> containing the value's Description attribute value if one exists; otherwise, the value name.
    17.     /// </value>
    18.     public string Description { get; set; }
    19.  
    20.     /// <summary>
    21.     /// Gets the enumerated constant value.
    22.     /// </summary>
    23.     /// <value>
    24.     /// An enumerated constant of the <b>EnumDescriptor's</b> generic parameter type.
    25.     /// </value>
    26.     public T Value { get; set; }
    27.  
    28.     /// <summary>
    29.     /// Creates a new instance of the <b>EnumDescriptor</b> class.
    30.     /// </summary>
    31.     /// <param name="value">
    32.     /// The value to provide a description for.
    33.     /// </param>
    34.     public EnumDescriptor(T value)
    35.     {
    36.         this.Value = value;
    37.  
    38.         // Get the Description attribute.
    39.         var field = value.GetType().GetField(value.ToString());
    40.         var descriptionAttribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
    41.                                         .Cast<DescriptionAttribute>()
    42.                                         .FirstOrDefault();
    43.  
    44.         // Use the Description attribte if one exists, otherwise use the value itself as the description.
    45.         Description = descriptionAttribute?.Description ?? value.ToString();
    46.     }
    47.  
    48.     /// <summary>
    49.     /// Overridden.  Creates a string representation of the object.
    50.     /// </summary>
    51.     /// <returns>
    52.     /// The friendly description of the value.
    53.     /// </returns>
    54.     public override string ToString()
    55.     {
    56.         return Description;
    57.     }
    58. }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width