Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Universal enumeration editor control

0.00/5 (No votes)
27 Dec 2004 1  
ASP.NET and WinForms control for editing any enumeration data type.

Asp.Net Control screenshot WinForms Control screenshot

Introduction

At first, I'd like to say that this control exists in two versions. First version is Windows Forms user control (namespace EeekSoft.WinForms.Controls) and second is web control that can be used from ASP.NET applications (namespace EeekSoft.Web.Controls). Each control is compiled to a single independent DLL file, so you can use first assembly in WinForms applications and second in web applications. Both controls have same (or very similar) functionality, so I decided to put these two controls in one article.

These controls can be used to allow users to enter value of any enumeration data type (in C#, it is enum and in VB.NET Enum data type). This is possible, thanks to reflection, because using reflection, the control can get all enumeration values and their names. One problem is that enumeration can be used for selecting one value from specified options or to store data as bitwise flags, and the control must be able to edit both of these types. Also, there are some other useful features that will be discussed later.

Background

This control generates a set of RadioButton or CheckBox (when enum allows to choose more values) controls. You can specify this using EditorType property, which can have one of the following values: Flags means that user can choose more values (CheckBoxes), Options means that user can choose only one value (RadioButtons), and third value is Auto. In the third case, control checks whether enumeration is marked using FlagsAttribute attribute (this is standard attribute used with enumerations) and behaves as Flags editor or Options editor automatically.

Reflection

Thanks to reflection, it is possible to edit any kind of enumeration using these controls. First interesting thing that I'd like to discuss is how to get list of all values of enum. Following code will first get System.Type object of enumeration using typeof operator. Then, it gets all its fields using GetFields method. This method returns array of all fields of type, so it is simple to loop through it and find all acceptable fields.

// First we need to get list of all enum fields

FieldInfo[] fields=typeof(MyEnum).GetFields();
foreach(FieldInfo field in fields)
{
  // Continue only for normal fields

  if (field.IsSpecialName) continue;

  // Parameter should be instance of object, but it is ignored

  // for static fileds (this case) so it is not important

  object valObj=field.GetValue(0));
  // Convert value to integer - this works only for enums which use Int32

  // for storing data (in control there is block of try-catch) 

  int val=(int)valObj;
  
  // Add control with specified value and title

  AddControl(val,field.Name);
}

Attributes

I also used attributes to control behavior of controls. I already mentioned attribute FlagsAttribute that is used for determining enumeration type. Other used attributes are from namespace System.ComponentModel. First attribute (BrowsableAttribute) is used to choose which values of enum should the user be able to select, and second (DescriptionAttribute) allows you to add description for each value.

Following code shows how to find out if field should be hidden (it is hidden when it is marked with attribute Browsable(false)) and get description of value. It uses method GetCustomAttributes, of FieldInfo which returns array with information about attributes of specified type.

// Array used for retrieving attributes

object[] attrs;

// Get array of BrowsableAttribute attributes

attrs=field.GetCustomAttributes(typeof(BrowsableAttribute),false);
if (attrs.Length==1)
{
  // If attribute exists and its value is false continue to the next field...

  BrowsableAttribute brAttr=(BrowsableAttribute)attrs[0];
  if (brAttr.Browsable==false) continue;
}

// Additional description for the field

string description="";
// Get DescriptionAttribute associated with the filed (if exists)

attrs=field.GetCustomAttributes(typeof(DescriptionAttribute),false);
if (attrs.Length>0) 
{
  description=((DescriptionAttribute)attrs[0]).Description;
}

How to use these controls

Both controls work similar, but there are some little differences that will be discussed later. In all examples, I will use following two enumerations. (First is marked with FlagsAttribute, so user can select more than one flag - control will generate CheckBoxes, and second, enum can be used to select only one of three values, so editor will contain RadioButtons):

// This enum is used for demonstration of flags editor functionality

[Flags]
enum MyFlagsEnum
{
  // Hidden fields (will not be displayed in editor)

  false)> None=0,
  false)> BothFlags=3,

  [Description("First flag")]  FirstFlag=1,
  [Description("Second flag")] SecondFlag=2,
  [Description("Third flag")]  ThirdFlag=4
}

// This enum is used for demonstration of options editor functionality

enum MyOptionsEnum
{
  [Description("First option")]  FirstOpt=1,
  [Description("Second option")] SecondOpt=2,
  [Description("Third option")]  ThirdOpt=3
}

WinForms control

If you want to add this control to your form, you can use designer. (If you want to add control to your toolbox, click on 'Add/Remove items' in toolbox context menu and select assembly with control.) You can modify only properties which affect control look in designer and the rest (enumeration type) can be changed only from code. ControlSpacing property specifies vertical offset of generated controls. LabelFormat property allows you to set format of text labels. You can use two parameters: {0} specifies name of value and {1} is description stored in DescriptionAttribute attribute. As I said before, you can override default controls behavior. If you want to use it as bitwise flags editor, set EditorType to Flags, and for choosing one option, use Options. One thing that can't be done using designer is to set type of enumeration (property EnumType as you can see in following example). Control has one event called Change that is raised when value of enumeration changes.

// Initialize enumeration editors

private void TestForm_Load(object sender, System.EventArgs e)
{
  // Flags editor

  myFlagsEditor.EnumType=typeof(MyFlagsEnum);
  myFlagsEditor.EnumValue=(long)
    (MyFlagsEnum.FirstFlag | MyFlagsEnum.SecondFlag);
    
  // Options editor

  myOptsEditor.EnumType=typeof(MyOptionsEnum);
  myOptsEditor.EnumValue=(long)MyOptionsEnum.ThirdOpt;
}

ASP.NET control

ASP.NET version of control is very similar to WinForms control. After you add control to toolbox, you can put it on the web form and set its design properties using Web Forms designer. But as in WinForms version, you must set type of edited enum manually (for example, in Page_Load event handler).

Only one important difference between properties of WinForms and ASP.NET controls: ASP.NET version doesn't have a ControlSpacing property (because I think it is better not to use absolute positioning in web applications for this). Instead of this, you can use ControlSeparator property to specify HTML tags which will control space put between every two generated RadiButtons or CheckBoxes. The default value for this property is <br />, but if you prefer to use table layout, you can simply modify it. Also, there is a little modification in event model. Property AutoPostBack allows you to set when page postback should occur. If you set it to true, page will do postback (and Change event will be called) whenever the value is changed, and if you set it to false, control will never raise postback and Change event will be called after page is sent back to the server for some other reason.

Following code sample shows how to add enum editor control to web form and how to use it from codebehind (code in cs file presumes, that you set event handler for Change event in designer):

<!-- EnumEditorDemo.aspx -->
<%@ Page language="c#" Codebehind="EnumEditorDemo.aspx.cs" 
    Inherits="WebFormsDemo.EnumEditorDemo" %>
<%@ Register TagPrefix="ec" Namespace="EeekSoft.Web.Controls"
    Assembly="EeekSoft.Web.EnumEditor" %>
...
  <ec:enumeditor id="myFlagsEditor" LableFormat="{0} - {1}" 
      runat="server" ControlSeparator="<br />"></ec:enumeditor>
  <asp:label id="valueLabel" runat="server"><asp:label>
...
// EnumEditorDemo.aspx.cs

private void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    // Set edited enumeration type and default value

    myFlagsEditor.EnumType=typeof(MyFlagsEnum);
    myFlagsEditor.EnumValue=(long)
      (MyFlagsEnum.FirstFlag | MyFlagsEnum.SecondFlag);
  }
}

// Value of edited enumeration changed

private void myFlagsEditor_Change(object sender, EventArgs e)
{
  // Show name of selected value using label

  valueLabel.Text=((MyFlagsEnum)myFlagsEditor.EnumValue).ToString();
}

Who can use it?

I think that both ASP.NET and WinForms versions of the control can be very useful if you want to allow user to modify settings of your application, and especially if you store this settings in enumerations. Typical use case may be when you load integer containing value of enumeration from database and you want to allow user to simply change its value and save it back to database. In this case, you can write a lot of code and add lot of CheckBox and RadioButton controls, or you can use this control and define structure of data very simply and clearly using enum (and this solution is also very easy to maintain).

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