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

Description Enum TypeConverter

Rate me:
Please Sign up or sign in to vote.
4.69/5 (35 votes)
3 Mar 20044 min read 234.4K   2.5K   71   55
This article explains how to manage to make a TypeConverter for enums using its descriptions.

Click to Enlarge

Click Image to Enlarge

Introduction

I had been looking everywhere about information on TypeConverters, specially their uses for the PropertyGrid. There's not much documentation about it, and I kinda needed it for some work stuff. That said, I'm presenting you here a simple EnumConverter which allows the use of the DescriptionAttribute to convert from and to the Enum values. This is great for presentation on a PropertyGrid, as you don't want either your Enum names appearing all over an application, neither you.

Background

I was in the process of creating a 3D engine in C#, and I was making tools to edit materials and a lot of more stuff. Each material, texture, etc, can have tons of properties, and I was aiming to discover a way of making my UI fast and with no mistakes. The usual way (making labels and textboxes/comboboxes/whatever) would be just too time-consuming, and I was (am) on a tight schedule. So I came across the PropertyGrid.

As the C# newbie I am, I started fiddling around the System.ComponentModel attributes to make my classes browsable on a PropertyGrid, so I first made 'Editable' wrappers which I'd only use on the tools (no need to overload the engine with things I won't use afterwards). This is a partial IBitmap editable class, so you know what I'm talking about:

C#
namespace Immerse.Editables
{
  [DefaultProperty("Name")]
  public class EditableIBitmap
  {
    private IBitmap bmp;
    
    public EditableIBitmap(IBitmap bmp) 
    {
      this.bmp = bmp;
    }

    [Browsable(false)]
    public IBitmap Bitmap { get { return bmp; } } 

    [Browsable(true), 
      DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [Category("Bitmap Properties"),Description("Bitmap Name")]
    [DefaultValue("Unnamed Bitmap")]
    public string Name { get { return bmp.Name; } }
    [Category("Bitmap Properties"),Description("Bitmap Width")]
    public int    Width { get { return bmp.Width; } }
    [Category("Bitmap Properties"),Description("Bitmap Height")]
    public int    Height { get { return bmp.Height; } }
    [Category("Bitmap Properties"),Description("Bitmap Depth")]
    public int    Depth { get { return bmp.Depth; } }
    [Category("Bitmap Properties"),Description("Bits per Pixel")]
    public int    Bpp { get { return bmp.Bpp; } }
    [Category("Bitmap Properties"),Description("Number of Dimensions (1-3)")]
    public int    Dimensions { get { return bmp.Dimensions; } }

    [Category("Bitmap Properties"),Description("Texture Tiling U")]
    public TextureTileTypes TileTypeU 
    { get { if(bmp.TileType.Length > 0) 
               return bmp.TileType[0]; 
            else return TextureTileTypes.Tile; } }
    [Category("Bitmap Properties"),Description("Texture Tiling V")]
    public TextureTileTypes TileTypeV 
    { get { if(bmp.TileType.Length > 1) 
                return bmp.TileType[1]; 
            else return TextureTileTypes.Tile; } }
    [Category("Bitmap Properties"),Description("Texture Tiling W")]
    public TextureTileTypes TileTypeW 
    { get { if(bmp.TileType.Length > 2) 
                return bmp.TileType[2]; 
            else return TextureTileTypes.Tile; } }
  }
}

So, this is not complete, but might give you a nice idea about how I got my editable wrappers implemented. Now, when put on a PropertyGrid, I'd get all the values. There's no setters put on this example, but you get the idea (I don't have them implemented like this, this is just an example).

So I made my own ColorPicker converter and some more stuff. Everything was working great, since it came the time of 'touching up' so it'd have a nice look, and was actually usable for other people than me. The main problem came with all different Enums I had on the program.

For example, TextureTileTypes, is an Enum like:

C#
public enum TextureTileTypes
{
  Tile,
  Clmp,
  ClmpB,
  ClmpE,
}

So in the PropertyGrid, my values would look like 'Tile','Clmp','ClmpB','ClmpE'. Not pretty much user-friendly, uh?

Trying to find some documentation in the net, everyone suggested that I should make a "TextureTileTypeConverter" and roll my own values... that's fine for one Enum, but not quite right for the tons of Enums I have spread all over my engine on possibly editable properties.

So, using the System.ComponentModel.DescriptionAttribute, I got to do this:

C#
public enum TextureTileTypes
{
  [Description("Tile")]            Tile,
  [Description("Clamp")]           Clmp,
  [Description("Clamp to Border")] ClmpB,
  [Description("Clamp To Edge")]   ClmpE,
}

They're, much easier to edit, much easier to code, and definitely no hassle to get a human-readable description of it. Now I just needed a way for the PropertyGrid to display the Description names, while still retaining the normal enum values for the setters. And that converter is what I'm presenting to you now.

Using the code

The code should be self-explanatory for anyone who has ever done any kind of custom TypeConverter for a PropertyGrid. You just set the ConverterAttribute of your editable class to typeof(EnumDescConverter), and that should do the trick.

Notice the following function:

C#
public static string GetEnumDescription(Enum value)
{
  FieldInfo fi= value.GetType().GetField(value.ToString());
  DescriptionAttribute[] attributes =
    (DescriptionAttribute[])fi.GetCustomAttributes
    (typeof(DescriptionAttribute), false);
  return (attributes.Length>0)?attributes[0].Description:value.ToString();
}

That should return the human-readable description set to the Enum value, if it has any, if it doesn't, then it just returns the Name as if you had done a ToString().

The other way around:

C#
public static string GetEnumName(System.Type value, string description)
{
  FieldInfo [] fis = value.GetFields();
  foreach(FieldInfo fi in fis)
  {
    DescriptionAttribute [] attributes =
      (DescriptionAttribute[])fi.GetCustomAttributes
      (typeof(DescriptionAttribute), false);
    if(attributes.Length>0)
    {
      if(attributes[0].Description == description)
      {
        return fi.Name;
      }
    }
  }
  return description;
}

So you can use those separately to retrieve any human-readable-form enum value, anywhere in your code. That should be useful enough by itself.

About (the juicy stuff), using the TypeConverter, just include the source file (EnumDescConverter.cs) somewhere in your project, and for your editable class (or however you want the browsing to be done), add typeof(Jcl.Util.EnumDescConverter), like this:

C#
[System.ComponentModel.TypeConverter(typeof(Jcl.Util.EnumDescConverter))]
public MyEnumType MyProperty
{ get { return myEnumVariable; } set { myEnumVariable = value; } }

Of course, you are 100% allowed to change the namespace and put it on your own :-)

Points of Interest

There are pretty much unbearable bugs appearing up when you start writing TypeConverters (as well as extending any other part of the .NET Framework), and most of them are very hard to find, as the documentation is not specially good yet, and there is no source for the .NET Framework, so there are many things going on the background which you can't just trace, as they are event-driven in the application. Once you get the rid of it though it's pretty easy to catch up.

License

You can use the code for free, you may include it in your applications, and you might modify it. Basically, do whatever you want with it. If you get to use it in your application, make sure you notify me about it, and credit would be appreciated, while not required.

History

First version of this document on 25th Feb 2004. Will try to make an example project soon.

Contact

You may contact me for anything related to this article at jcl at vmslabs dot com.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Chief Technology Officer La Boutique del Hogar
Spain Spain
I've been programming since 1994 and done projects in x86 Assembler, C, C++, Delphi and lately C#.

Comments and Discussions

 
GeneralCorrect source file is up Pin
Javier Campos4-Mar-04 21:04
Javier Campos4-Mar-04 21:04 
GeneralHere's the VB version Pin
robford1233-Mar-04 18:29
robford1233-Mar-04 18:29 
GeneralExcellent work Pin
Rui Dias Lopes3-Mar-04 8:32
Rui Dias Lopes3-Mar-04 8:32 
GeneralPretty cool... Pin
Mark Belles3-Mar-04 6:21
Mark Belles3-Mar-04 6:21 
GeneralWrong source code file Pin
Javier Campos3-Mar-04 4:43
Javier Campos3-Mar-04 4:43 

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.