c#枚举类型在web控件CheckBoxList,RadioButtonList,DropDownList中的应用

   在做web项目的时候经常使用CheckBoxList,RadioButtonList,DropDownList控件,对于这些控件的数据源如果需要客户动态维护的一般存于数据库中,但是大量的这些控件的数据源并不需要提供可视化的动态维护,如果直接在页面中写死则会存在重用性不强,后台代码编写容易出错等问题。现在我整理成使用枚举实现,重用性好,编写代码使用枚举值比较,不容易出错,虽然通过反射实现,性能并不是最好,但是个人觉得牺牲这么一点点性能还是值得的。具体代码分析如下:

 

首先是枚举的定义,这里定义了国家类型的枚举

 

/// <summary>
    
/// 国家
    
/// </summary>
    public enum Country
    {
        [ListItemText(
"中国")]
        China 
= 1,

        [ListItemText(
"美国")]
        America 
= 2,

        [ListItemText(
"德国")]
        Germany 
= 3,

        [ListItemText(
"英国")]
        England 
= 4,

        [ListItemText(
"法国")]
        France 
= 5,

        [ListItemText(
"日本")]
        Japan 
= 6
    }

该枚举中的枚举值,即1,2,3,4,5,6对应于CheckBoxList,RadioButtonList,DropDownList中的ListItem的value,即值。

枚举中的特性 ListItemText 对应于ListItem中的text。

输出到客户端的html如下(DropDownList示例)

    <select name="EnumSelect1" id="EnumSelect1">
    
<option selected="selected" value="1">中国</option>
    
<option value="2">美国</option>
    
<option value="3">德国</option>
    
<option value="4">英国</option>
    
<option value="5">法国</option>
    
<option value="6">日本</option>
 
</select>


定义继承自DropDownList的自定义控件,用于实现该枚举类型和DropDownList的整合。

EnumSelect 类
public class EnumSelect : System.Web.UI.WebControls.DropDownList
    {

        
/// <summary>
        
/// 在页面中设置该控件的枚举类型名称,必须设置
        
/// </summary>
        public string EnumTypeName { getset; }

        
protected override void OnLoad(EventArgs e)
        {
            
base.OnLoad(e);

            
if (Page.IsPostBack) return;

            var a 
= Assembly.Load("WebApplication");

            
if (string.IsNullOrEmpty(EnumTypeName))
                
throw new Exception("必须设置属性EnumTypeName的值");


            var t 
= a.GetType(EnumTypeName);
            var list 
= Util.GetListItemFromEnum<int>(t);

            
foreach (ListItem li in list)
            {
                
this.Items.Add(li);
            }
        }
    }

该类只需要设置一个属性EnumTypeName 即枚举的具体类型就可以(类型为全名,需要包含命名空间)

在页面中使用该控件设置EnumTypeName 属性值:

 

 <cc1:EnumSelect ID="EnumSelect1" runat="server" EnumTypeName="WebApplication.Country">
        
</cc1:EnumSelect>

 

编译完之后可以从工具箱的自定义组件中拖拉到页面中
 

 

EnumSelect1类中的Util类如下:

 

Util 类
public class Util
    {
        
/// <summary>
        
/// 根据一个枚举类型转化成ListItemCollection
        
/// </summary>
        
/// <param name="enumType">枚举类型</param>
        
/// <returns></returns>
        public static ListItemCollection GetListItemFromEnum<T>(Type enumType)
        {
            var list 
= new ListItemCollection();

            
if (enumType.IsEnum != true){
                
throw new Exception("方法GetListItemFromEnum只能接受枚举类型");
            }

            var typeText 
= typeof(ListItemTextAttribute);

            
//获得枚举的字段信息(因为枚举的值实际上是一个static的字段的值)
            var fields = enumType.GetFields();

            
foreach (var fi in fields)
            {
                
if (!fi.FieldType.IsEnum) continue;

                
//获得这个字段的所有自定义特性,这里只查找ListItemTextAttribute特性
                var arr = (ListItemTextAttribute[])(fi.GetCustomAttributes(typeof(ListItemTextAttribute), true));

                
if (arr.Length <= 0continue;

                var li 
= new ListItem
                             {
                                 Value 
=
                                     Convert.ChangeType(
                                         enumType.InvokeMember(fi.Name, BindingFlags.GetField, 
nullnullnull),
                                         
typeof (T)).ToString()
                             };

                
//因为ListItemTextAttribute这个自定义特性是不允许重复的,所以我们只取第一个就可以了!
                var a = (ListItemTextAttribute)arr[0];

                
//获得特性的描述值,也就是‘男’‘女’等中文描述
                li.Text = a.Text;

                list.Add(li);
            }

            
return list;
        }

        
/// <summary>
        
/// 根据枚举值获得指定的ListItemTextAttribute的值
        
/// </summary>
        
/// <typeparam name="T">必须为枚举类型</typeparam>
        
/// <param name="e"></param>
        
/// <returns></returns>
        public static string GetEnumListItemText<T>(T e)
        {
            var t 
= typeof(T);

            
if (!t.IsEnum)
            {
                
throw new Exception("泛型参数必须为枚举类型");
            }

            var mis 
= t.GetMember(e.ToString());

            
if (mis.Length != 1)
            {
                
throw new Exception("无法找到该枚举属性或者该枚举属性数量大于1");
            }

            var arr 
= (ListItemTextAttribute[])mis[0].GetCustomAttributes(typeof(ListItemTextAttribute), false);

            
if (arr.Length == 0)
            {
                
throw new Exception("未指定该枚举属性的Text值");
            }

            
return arr[0].Text;
        }
    }

Util类有两个方法:

1.GetListItemFromEnum方法: 传入一个具体的枚举类型,返回 CheckBoxList,RadioButtonList,DropDownList控件需要的数据源ListItemCollection。

2.GetEnumListItemText方法: 传入一个枚举值,比如Country.China,返回的是具体的text,这里返回 “中国”。

 如果是根据具体的选中项来取得文本值,则代码如下

  var province = string.Empty;
            
if (!string.IsNullOrEmpty(EnumRadioButtonList1.SelectedValue))
                province 
= Util.GetEnumListItemText<Province>((Province)(int.Parse(EnumRadioButtonList1.SelectedValue)));


 最后还有一个重要的特性类没有介绍,具体代码如下:

/// <summary>
    
/// 枚举类型的字段 ListItem Text 特性
    
/// </summary>
    [AttributeUsage(AttributeTargets.Field)]
    
public class ListItemTextAttribute : Attribute
    {
        
public ListItemTextAttribute(string text)
        {
            
this.Text = text;
        }

        
public string Text { getset; }
    }


 

 

 

在可以下载的代码包中我已经分别实现了  CheckBoxList,RadioButtonList,DropDownList控件和枚举的整合自定义控件。

分别是 EnumCheckBoxList,EnumRadioButtonList,EnumSelect

 

Demo界面


 

 在可下载的代码包中对这三个控件都有demo演示的,可以直接运行,VS2008编写

以下是全部代码,可以直接下载

/Files/szp1118/WebApplication.rar 

 

 


posted @ 2010-07-15 16:53  喆_喆  阅读(1582)  评论(4编辑  收藏  举报