Universal enumeration editor control






4.80/5 (12 votes)
ASP.NET and WinForms control for editing any enumeration data type.
- Download source files - 12.4 Kb
- Download demo applications - 36.9 Kb
- Download controls documentation - 41.1 Kb
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 (CheckBox
es), Options
means that user can choose only one value (RadioButton
s), 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 CheckBox
es, and second, enum
can be used to select only one of three values, so editor will contain RadioButton
s):
// This enum is used for demonstration of flags editor functionality
[Flags]
enum MyFlagsEnum
{
// Hidden fields (will not be displayed in editor)
[Browsable(false)] None=0,
[Browsable(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 RadiButton
s or CheckBox
es. 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).