Universal enumeration editor control
- Download source files (22 kB)
- Download demo applications (58 kB)
- Download controls documentation (42 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 single independent dll file, so you can use
first assembly in win forms application and second in web application. Both controls has same (or very similar) functionality
so I decided to put this two controls in one article.
This controls can be used to allow user 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 reflections, because using reflection control can get all
enumeration values and its 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 this types. Also there are some
other usefull features that will be discussed later.
Background
This control generates 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 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 automaticly.
Reflection
Thanks to reflection it is possible to edit any kind of enumeration using this 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. Than 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
thath
is used for determinating enumeration type. Other used attributes are from namespace
System.ComponentModel
. First attribute (BrowsableAttribute
) is used to choose which
values of enum should be user 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 this 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 flags - 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 it's 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 is that 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 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 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 control can be very usefull 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 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).