綁定Enum到ASP.NET數據綁定控件的完美解決方案[05/26修訂]——增加支持第三方枚舉描述,支持二進制與過的枚舉值

本文向讀者介紹NBear中實現的DropDownListField字段綁定控件和EnumDescriptionAttribute特性。結合使用這兩個組件,就可以最簡單、易用和可擴展地完美解決綁定Enum到ASP.NET數據綁定控件的問題。[05/26修訂]——增加支持第三方枚舉描述,支持二進制與過的枚舉值。

從DropDownListField的名稱,大家一定猜到了,是的,DropDownListField控件和ASP.NET內置的BoundField,CheckBoxField等一樣,可以直接用於GridView,DetailsView等控件的聲明中,用於描述一個Enum類型的字段的綁定。使用DropDownListField,我們就再也不需要向原來一樣爲了綁定一個Enum類型的值而使用自定義ItemTemplate並嵌入DropDownList,並寫額外代碼來填充ItemTemplate中的DropDownList了。

首先,我們看看如何在我們的頁面代碼中使用DropDownListField控件:

 1ExpandedBlockStart.gif<%@ Page Language="C#" %>
 2ExpandedBlockStart.gif<%@ Register TagPrefix="nb" Namespace="NBear.Web.Data" Assembly="NBear.Web.Data" %>
 3None.gif<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4None.gif<html xmlns="http://www.w3.org/1999/xhtml" >
 5None.gif<head runat="server">
 6None.gif    <title>NBear DataSource Test</title>
 7None.gif</head>
 8None.gif<body>
 9None.gif<form id="aspnetForm" runat="server">
10None.gif    <nb:NBearDataSource ID="TestDS" runat="server" ConnectionStringName="test access db"
11None.gif        TypeName="Entities.SimpleData" FilterExpression="{SimpleID} > 0" DefaultOrderByExpression="{SimpleID} DESC, {SimpleName}" />
12None.gif    <asp:GridView ID="TestGrid" runat="server" DataSourceID="TestDS" AllowSorting="True" AllowPaging="True"
13None.gif        PageSize="3" AutoGenerateEditButton="True" AutoGenerateDeleteButton="True" DataKeyNames="SimpleId" AutoGenerateColumns="False" >
14None.gif        <Columns>
15None.gif            <asp:BoundField DataField="SimpleId" HeaderText="SimpleId" SortExpression="SimpleId" />
16None.gif            <asp:BoundField DataField="SimpleName" HeaderText="SimpleName" SortExpression="SimpleName" />
17None.gif            <asp:CheckBoxField DataField="BoolVal" HeaderText="BoolVal" SortExpression="BoolVal"
18None.gif                Text="BoolVal" />
19None.gif            <nb:DropDownListField DataField="Status" HeaderText="Status" SortExpression="Status" EnumType="EntityDesigns.SimpleStatus" />
20None.gif        </Columns>
21None.gif    </asp:GridView>
22None.gif    <br />
23None.gif    <asp:DetailsView ID="TestDetail" runat="server" DataSourceID="TestDS" DefaultMode="Insert"
24None.gif            AutoGenerateInsertButton="True" AutoGenerateRows="False">
25None.gif        <Fields><asp:BoundField DataField="SimpleName" HeaderText="Name" />
26None.gif            <asp:CheckBoxField DataField="BoolVal" HeaderText="BoolVal" />
27None.gif            <nb:DropDownListField DataField="Status" HeaderText="Status" EnumType="EntityDesigns.SimpleStatus" />
28None.gif        </Fields>
29None.gif    </asp:DetailsView>
30None.gif</form>
31None.gif</body>
32None.gif</html>

請注意第2和第19,27行。在頁面中,首先要註冊NBear.Web.Data命名空間。接着,在數據控件的Columns中,添加DropDownListField就行了,和ASP.NET內置的的CheckBoxField使用中的唯一區別是,DropDownListField必須額外設置一個EnumType屬性,顧名思義,就是綁定到這個控件Enum字段的類型的FullName。

OK,就是這麼簡單。本頁面中使用到的SimpleStatus如下:

1None.gif    public enum SimpleStatus
2ExpandedBlockStart.gif    {
3InBlock.gif        Value1 = 1,
4InBlock.gif        Value2 = 2
5ExpandedBlockEnd.gif    }

如果運行這個頁面,您將可以看到DropDownList中顯示的是Value1和Value2。

-

等1秒鐘,你一定要說,這還不是我想要的,因爲,我需要枚舉值在DropDownList中顯示的文字描述是我需要的自定義信息。

OK,接着就輪到本文的第二個主角——EnumDescriptionAttribute了。

只需要如下使用EnumDescriptionAttribute標註Value1和Value2就行:

1None.gif    public enum SimpleStatus
2ExpandedBlockStart.gif    {
3InBlock.gif        [NBear.Common.EnumDescription(DefaultDescription="Desc of Value1")]
4InBlock.gif        Value1 = 1,
5InBlock.gif        [NBear.Common.EnumDescription(DefaultDescription="Desc of Value2")]
6InBlock.gif        Value2 = 2
7ExpandedBlockEnd.gif    }

OK,不需要任何額外設置了,再運行上面的頁面,您將能看到DropDownList中顯示的文字是我們指定的自定義信息了。很酷不是嗎?

-

再等一秒鐘,我們還是不會滿足的,雖然我們可以指定自定義說明信息,但是,如果是多語言環境,我們需要運行時對枚舉值的顯示不同的文字信息,還有很多情況,我們需要從數據庫中的枚舉描述表讀取對枚舉的描述信息。

對此,我們當然也提供瞭解決方案。

我們只需要繼承EnumDescriptionAttribute即可。下面的MyEnumDescriptionAttribute演示了一個自定義的枚舉描述實現:

1None.gif    public class MyEnumDescriptionAttribute : NBear.Common.EnumDescriptionAttribute
2ExpandedBlockStart.gif    {
3ExpandedSubBlockStart.gif        private static string[] customDescs = new string[] "custom desc of Value1"null };    //the second value is null here to use the DefaultDescription set in enum definition
4InBlock.gif
5InBlock.gif        public override string GetDescription(object enumValue)
6ExpandedSubBlockStart.gif        {
7InBlock.gif            return customDescs[(int)enumValue] ?? base.GetDescription(enumValue);
8ExpandedSubBlockEnd.gif        }

9ExpandedBlockEnd.gif    }

這個類重載了EnumDescriptionAttribute的GetDescription()方法,從一個內存中的數組中讀取描述信息。類似的,我們也可以在這裏從資源文件或者數據庫中讀取說明信息,都只需要重載這個方法就可以了。

您一定注意到其中的註釋代碼了,假如,對某個枚舉值,我們的自定義方法取不到自定義的描述信息,那麼,它會首先查看對這個枚舉值標註的MyEnumDescriptionAttribute有沒有指定DefaultDescription,如果制定則返回這個內容,否則就返回枚舉值的ToString()內容。

使用MyEnumDescriptionAttribute描述SimpleStatus如下:

1None.gif    public enum SimpleStatus
2ExpandedBlockStart.gif    {
3InBlock.gif        [MyEnumDescription(DefaultDescription="Default Desc of Value1")]
4InBlock.gif        Value1 = 1,
5InBlock.gif        [MyEnumDescription(DefaultDescription="Default Desc of Value2")]
6InBlock.gif        Value2 = 2
7ExpandedBlockEnd.gif    }


再次運行頁面,您將看到,DropDownList中對應Value1顯示的信息爲custom desc of Value1,而對應Value2顯示的信息爲Default Desc of Value2。爲什麼呢?因爲對Value1我們能取到MyEnumDescriptionAttribute返回的自定義信息,而對Value2,MyEnumDescriptionAttribute返回null,那麼,默認的描述信息將被應用。是不是很神奇呢?

甚至,您可以對同一個Enum類型的不同成員項混合使用不同的EnumDescriptionAttribute或其繼承類來指定描述信息(有這樣的需求嗎^-^)。但是,每個枚舉項只有第一個EnumDescriptionAttribute或其繼承類標註會生效,多餘的標註會被忽略。

 好了,基本介紹完了,斗膽稱這個方案爲完美方案,別扔臭雞蛋就好。:)


篇後語

除了結合數據綁定控件使用EnumDescriptionAttribute之外,您也可以單獨使用EnumDescriptionAttribute以透明獲取的枚舉值描述信息。調用EnumDescriptionAttribute.GetDescriptions(enumType)這個靜態方法就可以得到指定枚舉類型的所有枚舉值的由EnumDescriptionAttribute或其繼承類標註的描述信息。

DropDownListField類是參考ASP.NET內置的CheckBoxField類寫的。


下載

本文介紹的組件的全部源碼和示例代碼包含於最新版本的nbear中,EnumDescriptionAttribute定義於src/NBear.Common/EnumDescriptionAttribute.cs,DropDownListField定義於src/NBear.Web.Data/DropDownListField。示例程序位於tutorials/NBearDataSourceSample。

可以從NBear的官方網站下載:http://nbear.org

-

[05/26修訂]——增加支持第三方枚舉描述,支持二進制與過的枚舉值。包含於NBearV3.7.1 build 7以上版本。

1、對於在第三方已編譯程序集中的枚舉類型,也就是說我們沒有機會直接添加EnumDescriptionAttribute到枚舉定義的,現在也支持了。只需要額外定義一個與外部枚舉類型對應的枚舉類型,保證兩個枚舉類型的枚舉項的int值相等即可,在這個新枚舉類型中標註EnumDescriptionAttribute即可。當然,此時,EnumType屬性需要填新的枚舉類型名稱。

2、對於枚舉值支持二進制與的枚舉值,現在也支持了,無需額外設置。不過這種枚舉值的insert和edit如果需要更新爲合併值,還是需要用戶自行寫代碼完成。這裏僅僅是支持到顯示這樣的值。

//本文結束



發佈了187 篇原創文章 · 獲贊 1 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章