| 經(jīng)常會(huì )碰到在前臺代碼中要使用(或綁定)后臺代碼中變量值的問(wèn)題。一般有<%= str%>和<%# str %>兩種方式,這里簡(jiǎn)單總結一下。如有錯誤或異議之處,敬請各位指教。 備注:上面說(shuō)的兩個(gè)文件是常見(jiàn)的代碼隱藏(code-behind)模式,還有一種是代碼嵌入(code-beside, inline)模式,那就是只存在aspx一個(gè)文件,而后臺代碼則寫(xiě)入此文件的<script type="text/javascript" runat="server"></script>之中(還有一些語(yǔ)法上區別),這對于本文討論的問(wèn)題略有影響,因為代碼嵌入是聲明性代碼與C#/VB.NET代碼都一起編譯到一個(gè)類(lèi)里面,而代碼隱藏則將聲明性代碼與C#/VB.NET代碼分開(kāi)幾次進(jìn)行翻譯/編譯,因此前者是局部與局部(partial)的關(guān)系后者基類(lèi)與派生類(lèi)的關(guān)系,但這僅僅影響所能綁定變量的范圍(與修飾符有關(guān)),下面會(huì )提到。以下均以代碼隱藏模式為例。 一般來(lái)說(shuō),在前臺代碼的三種位置可能會(huì )用到(綁定)后臺變量: •服務(wù)器端控件屬性或HTML標簽屬性 (1)一般的屬性要求是字符串型或數值型(下面會(huì )提到有些服務(wù)器端屬性支持屬性為數據集合); (2)并不是所有的屬性都可以綁定變量,有些屬性例如runat屬性必須是"server"常量,即使綁定的字符串是server,也會(huì )導致分析器分析時(shí)出錯; (3)有一種屬性,他要求屬性值有約束(類(lèi)型約束,比如服務(wù)器端控件要求TabIndex屬性是short類(lèi)型,或者字符串內容有約束),也應該在綁定時(shí)滿(mǎn)足,否則依然可能編譯時(shí)報錯; (4)還一種屬性,雖然屬性本身有約束,但即使綁定的變量不滿(mǎn)足約束,也可以編譯通過(guò),比如input的checked屬性,它只有checked字符串是合法的,但如果通過(guò)綁定獲取到的字符串不是checked,那么這些屬性將有自己內部處理機制,來(lái)保證可以正常使用; (5)還要注意,即使對于同一類(lèi)屬性,服務(wù)器端和HTML的屬性的處理機制也不同,同樣是TabIndex(tabIndex),前者如果不滿(mǎn)足,則分析器錯誤,后者則忽略這一問(wèn)題。 對于第二種位置,一般只要綁定的后臺變量和JavaScript中數據類(lèi)型兼容即可。 對于第三種位置,如果綁定出現的位置不在服務(wù)器端控件內部,則沒(méi)有約束條件,只要是常量字符串可以出現的位置,均可以綁定。但是對于置于服務(wù)器端控件內部,也就是上面那種<asp:Label ID="Label2" runat="server" Text="Label">這里</asp:Label>的方式,則有約束條件。通過(guò)總結,歸納為四類(lèi)服務(wù)器端控件,如果綁定的代碼出現在這些控件的開(kāi)始和結束標簽之間(這里所說(shuō)的控件,是指如果綁定代碼外有多層的嵌套控件包圍,則是指包圍綁定代碼的最內層控件),有不同的顯示結果: (1)約束型控件:這類(lèi)控件要求它的開(kāi)始標簽和結束標簽中只能包含指定的子控件,因此如果在這里出現代碼塊,將編譯錯誤。例如: <asp:DataList runat="server"></asp:DataList>,在它之間,要求必須嵌套<ItemTemplate></ItemTemplate>。 (2)非嵌套類(lèi)控件:這類(lèi)控件,不允許在內部嵌套其他控件或標簽,只能是常量字符串,它會(huì )將開(kāi)始標簽和結束標簽中常量字符串內容作為他的屬性。例如上面提到的TextBox,它會(huì )將標簽間內容作為它的Text屬性值。 (3)嵌套類(lèi)控件:這類(lèi)控件,可以嵌套其他任意控件,也可以包含字符串,因此可以正常顯示綁定代碼塊所表示的字符串內容。例如Label控件、Panel等。 (4)數據綁定類(lèi)控件:這類(lèi)控件是ASP.NET提供的服務(wù)器端控件,除了可以綁定普通的變量類(lèi)型,也可以綁定一個(gè)數據集合(只能采取下面的第二種方式實(shí)現)。 關(guān)于是否加引號:在以上三個(gè)位置使用時(shí),是否應該將<%= str%>或<%# str %>置于單引號或雙引號中呢?對于在不同位置,處理的方式是不同的:(具體請在下面兩種方式的具體介紹時(shí),加以體會(huì )) (1)對于第一種位置,由于JavaScript是弱類(lèi)型的,如果綁定時(shí)加引號,顯然就認為就當做字符串來(lái)處理,這始終是正確的;如果綁定時(shí)不加引號,它將認為這是個(gè)數值型的,那么如果獲取的真是數值,當然可以,如果是非數值型,則將產(chǎn)生腳本錯誤,這即使對于JavaScript賦值常量時(shí),也是同樣的: var test1 = 123b;//運行時(shí)報錯 •對于服務(wù)器端控件屬性,如果綁定的代碼塊不加引號,則編譯時(shí)會(huì )提示“驗證(ASP.NET):特性值前后必須加引號”的警告信息,但是生成為HTML后,對應生成的HTML屬性已經(jīng)被加上引號并獲取了正確的綁定結果,因此加不加引號不會(huì )影響使用,但是建議對于規范的代碼,還是加上為好; 因此建議,所有綁定表達式都加上引號,作為字符串獲取,然后根據實(shí)際需求,用相應函數進(jìn)行轉換,得到所需要的類(lèi)型。 另外,這里所說(shuō)的后臺變量是泛指的,包括如下: •成員變量 (1)變量修飾符要求。變量是靜態(tài)或者實(shí)例字段均可。對于代碼隱藏模式的ASP.NET,以上的所述的變量必須為public或protected類(lèi)型(因為是基類(lèi)與派生類(lèi)的關(guān)系),private或者internal都不行,而代碼嵌入模式則任何修飾符的變量均可訪(fǎng)問(wèn)(一個(gè)類(lèi)內部的關(guān)系)。 (2)變量類(lèi)型要求。由于前臺屬性一般是字符串類(lèi)型,而JavaScript基本類(lèi)型也就是字符串型、數字型、布爾型,因此對應的變量應該也是這幾種方式,其余類(lèi)型如果不被支持(如復雜類(lèi)型、數組、引用類(lèi)型等),前臺獲取的就是調用了變量的ToString()方法所得到的字符串。因此,在綁定時(shí),要根據情況看是否能進(jìn)行隱式類(lèi)型轉換,必要時(shí)還要用相關(guān)函數來(lái)強制轉換,以保證前臺可以獲得正確的值。當然,對于數據綁定類(lèi)控件,它的有些屬性可以為數據集合,但這時(shí)的綁定只能通過(guò)下面第二種方式才被支持。 以上是一些概念和基本約束,這些都是兩種方式都應該滿(mǎn)足的,下面具體介紹兩種方式,來(lái)實(shí)現前臺代碼中(以下稱(chēng)為代碼塊)綁定后臺變量的功能。 一. <%= str%> 此種方式其實(shí)是ASP 時(shí)代就支持的,ASP 通過(guò)包含在 < % 和 %>中的表達式將執行結果輸出到客戶(hù)瀏覽器 , 如:< % =test %>就是將變量test的值發(fā)送到客戶(hù)瀏覽器中。在A(yíng)SP.NET中,這個(gè)表達式依然可以使用,并可以出現在前臺代碼的上述三個(gè)位置,但是要注意,除了上述的一般性約束外,對于控件屬性,還必須是綁定到非服務(wù)器端控件的屬性。另外,它只能綁定上面講的前三種變量類(lèi)型,不支持綁定數據集合。例子如下: 后臺代碼: public partial class WebForm2 : System.Web.UI.Page <html xmlns="<head> var str = '<%= DateTime.Now %>'; 之所以說(shuō)第一種綁定方式要用于非服務(wù)器端控件的屬性,是因為如果應用于這些服務(wù)器端屬性時(shí),這些代碼實(shí)際上不被解析。 比如: <asp:Label ID="Label1" runat="server" Text="<%= GetVariableStr %>"></asp:Label> 這里結合開(kāi)篇提到的關(guān)于將綁定代碼快置于“Html顯示內容的位置”時(shí),如果在服務(wù)器端控件內,那四類(lèi)控件如何顯示的問(wèn)題。如下: <asp:Label ID="Label1" runat="server" >"<%= GetVariableStr %>"</asp:Label> 二. <%# str %> ASP.NET 引入了一種新的聲明語(yǔ)法 <%# %>。該語(yǔ)法是在 .aspx 頁(yè)中使用數據綁定的基礎,所有數據綁定表達式都必須包含在這些字符中。這里從用法和適用范圍等方面與第一種綁定方式進(jìn)行區分。 從出現的位置來(lái)看,除了能出現在第一種代碼塊出現的所有位置外,他還可以出現在服務(wù)器端控件的屬性中。 從綁定的變量類(lèi)型上看,他還可以配合ASP.NET的數據綁定類(lèi)控件,來(lái)綁定上述的第四種“變量”類(lèi)型,就是數據集合(DropDownList,DataList,DataGrid,ListBox這些是數據綁定類(lèi)控件,數據集合包括ArrayList(數組),Hashtable(哈稀表,DataView(數據視圖),DataReader等)。 從用法上看,在前臺代碼中除了在相應位置寫(xiě)上<%# %>外,在后臺代碼中,還需要使用DataBind()方法。以下是實(shí)例: 前臺代碼: <html xmlns="<head> var str = '<%# DateTime.Now %>'; alert(str); 后臺代碼: public partial class WebForm2 : System.Web.UI.Page arraylist = new ArrayList(); dt = new DataTable(); Page.DataBind(); 兩者區別: 兩種綁定方式上,他們的約束基本相同,都要求與屬性匹配,出現在他們可以出現的位置。后者的使用位置更廣泛,尤其是支持服務(wù)器端控件和綁定數據集合。后臺代碼方面,后者需要調用DataBind才能完成綁定,前者則沒(méi)有這方面要求。這里主要區別一下兩者在執行機制上的區別:<%=...%>是在程序執行時(shí)調用(應該是在頁(yè)面的RenderControl事件過(guò)程中完成的,也就是通常情況下我們可以看到的后臺代碼都執行完畢后再去到前臺代碼中進(jìn)行賦值綁定),而<%#... %>是在DataBind()方法之后被調用,一旦調用了DataBind(),則它對應的控件將綁定變量,因此,請注意:如果在DataBind()后再修改變量,那么綁定的就不是最新值了,這就需要在完成變量的賦值后,再去DataBind()。其實(shí)這兩種方式,它的運行過(guò)程可以在VS中通過(guò)設置斷點(diǎn)來(lái)看看,看兩者的綁定賦值分別是在什么時(shí)候發(fā)生的。 尚存的疑問(wèn): 1.不知道為什么不能獲取到internal修飾的變量? 參考文章: ASP.NET 數據綁定概述 asp.net代碼中尖括號和百分號的含義 Page.DataBind()方法 Eval( " ")和DataBinder.Eval(Container.DataItem, " ")的區別及用法 體會(huì )Bind和Eval的不同用法 深入理解 ASP.NET 動(dòng)態(tài)控件 (Part 2 - 編譯過(guò)程) <%# Eval("name")%>與<%# Bind("name")%>區別 |
聯(lián)系客服