HiddenField控件顧名思義就是隱藏輸入框的伺服器控件,它能讓你保存那些不需要顯示在頁面上的且對安全性要求不高的資料。也許這時候應該有這麼一個疑問,為什麼有了ViewState、Session和Cookie等狀態保存機制,還需要用起HiddenField呢?
增加HiddenField,其實是為了讓整個狀態管理機制的應用程度更全面。因為不管是ViewState、Cookie還是Session,都有其失效的時候,例如使用者因某種需求要求設定ViewState為false,或是環境條件限制使用Cookie,或使用者長時間沒有動作導致Session過期等等,那這個時候HiddenField無疑是最佳選擇。
HiddenField控制項的作用簡單的說是用來儲存需要在向伺服器的傳送間保持的值。它以<input type= "hidden"/> 元素呈現,並且透過新增runat=”server”就可以使它成為標準的HTML伺服器控制項。以下列出的是ASP.NET HiddenField Web伺服器控制項可以使用的屬性和事件。
<asp:HiddenField
EnableTheming="True|False"
EnableViewState="True|False"
ID="string"
OnDataBinding="DataBinding event handler"
OnDisposed="Disposed event handler"
OnInit="Init event handler"
OnLoad="Load event handler"
OnPreRender="PreRender event handler"
OnUnload="Unload event handler"
OnValueChanged="ValueChanged event handler"
runat="server"
SkinID="string"
Value="string"
Visible="True|False"
/>
因為HiddenField 的值將呈現給客戶端瀏覽器,所以它不適用於儲存安全敏感的值。若要為HiddenField 控制項指定值,請使用Value 屬性,請注意是Value而不是Text。事實上HiddenField並沒有Text屬性,這和DropDownList、CheckBoxList等標準按鈕的屬性命名方式一致。在標準的屬性命名方式中,Text的值是呈現給使用者看到的,而Value的值則是通長是透過程式碼控制的。例如你可以讓DropDownList的Text屬性顯示用戶名而讓它的Value儲存用戶的編號。
下面的程式碼顯示的是改控件的基本使用。
<html>
<head>
<script language="C#" runat="server">
void Button1_Click(object sender, EventArgs e)
{
if (HiddenField1.Value == String.Empty)
HiddenField1.Value = "0";
HiddenField1.Value = (Convert.ToInt32(HiddenField1.Value)+1).ToString();
Label1.Text = HiddenField1.Value;
}
</script>
</head>
<body>
<h3><font face="Verdana">HiddenField</font></h3>
<form runat=server>
<asp:HiddenField id=HiddenField1 runat=Server />
<asp:Button id=Button1 Text="點選按鈕" onclick="Button1_Click" runat="server" />
點選<asp:Label id=Label1 Text="0" runat=server /> 次
</form>
</body>
</html>
在上述程式碼中, <asp:HiddenField id=HiddenField1 runat=Server />就定義了一個隱藏控制項在按鈕的點選事件中計算使用者點選的次數,並將改次數賦值給Label1。
你可以將上面程式碼中的 <asp:HiddenField id=HiddenField1 runat=Server />改為<input type=hidden id=HiddenField1 runat=Server >也是可以的
使用上面程式碼裡,如果你從瀏覽器查看來源程式碼會得到如下的資訊:
<form name="Form1" method="post" action="Default.aspx" id="Form1">
這是因為HiddenField是透過HTTP協定傳遞資料的,所以如果你透過" method="get"或連結開啟新的窗體頁,那麼HiddenField並不可用。
另外,HiddenField並不是取代Session來維護狀態的,在上面例子裡,雖然你點擊一次按鈕可以顯示你點擊的次數但是並不是說它可以記錄你的狀態資訊。如果你重新打開瀏覽器那麼你看到的這裡仍然是0而不是3。
HiddenField事件
HiddenField較為常用的是ValueChanged事件,此事件會在Value值改變時觸發此事件。然而在實際使用時,要知道頁面記載順序。在頁面回傳過程中,具體的頁面週期你可以到以下網站查看
http://msdn2.microsoft.com/zh-cn/library/ms178472.aspx
下面的例子說明了這個問題
<head>
<script runat="server" language="c#">
protected void Page_Load(object sender, EventArgs e)
{ Response.Write("<p>頁面的Page_Load事件觸發,觸發時間是:" + DateTime.Now.ToString());
if (HiddenField1.Value == String.Empty)
HiddenField1.Value = "0"; }
protected void Button1_Click(object sender, EventArgs e)
{ Response.Write("<p>Button1_Click為改變Hidden的值前事件觸發,觸發時間是:" + DateTime.Now.ToString( ));
HiddenField1.Value = (Convert.ToInt32(HiddenField1.Value) + 1).ToString();
Label1.Text = HiddenField1.Value;
}
protected void HiddenField1_ValueChanged(object sender, EventArgs e)
{ Response.Write("<p>HiddenField的ValueChanged事件觸發,觸發時間是:" + DateTime.Now.ToString());
</script>
</head>
<body>
<form id="form1" runat="server">
<div> <asp:HiddenField ID="HiddenField1" runat="server" OnValueChanged="HiddenField1_ValueChanged" />
</div> <asp :Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text=" Button" />
</form></body>
</html>
在這個例子裡,我們想要的結果是:當使用者點擊按鈕時,透過按鈕的Button1_Click事件更改HiddenField1的Value,然後再觸發HiddenField1的HiddenField1_ValueChanged事件,然而事實真的如此嗎?
運行上面的程式碼,得到的結果正如你所看到的,每次點擊時,Button確實改變了HiddenField的值,但是我們在HiddenField1_ValueChanged裡定義的輸出並沒有執行,換句話說頁面並沒有執行ValueChanged事件要要理解這個問題也需要了解頁面的宣告週期,在頁面週期過程中,你可以看到在Page_Init裡是讀取或初始化控制項屬性,然後再是Control events。
這裡的事件意思是說: 在Page_Init事件裡,Web頁面會接受使用者回傳的數據,例如將<span id="Label1">Label</span>賦值給ID為Label1的Text屬性,將<input type ="hidden" name="HiddenField1" id="HiddenField1" value="0" />的value值賦值給HiddenField1的Value屬性。等所有初始化完畢了,頁面才開始執行控制項的事件-Button1_Click,在Button事件裡將HiddenField的Value值改變。那這裡既然已經將Value值改變為什麼沒有執行ValueChanged事件呢?
此時,雖然這裡已經將Value值改變,但是在Page_Init裡保存的這是因為當前單擊Button按鈕時,雖然改變了HiddenField但同樣又一次觸發了頁面的回复,也就是雖然在上一此HiddenValue的值為0,而此次將其值改為1,但在頁面回傳後,由於ViewState會保存上次的裝(這裡是1),所以在Page_Init裡,認為HiddenField的初始值為1,而本次還是1,使得它感覺資料沒有變化,所以仍然不會觸發ValueChanged事件
當然,你可以禁用HiddenField來進行處理,就可以執行ValueChanged事件,但是事實上你禁用ViewState後,頁面不再保存ViewState的值使得頁面認為每次請求HiddenField的都是新的,例如以下程式碼:
你並沒有改變Hiddenfield的值,但是仍然每次都執行。
<%@ Page EnableViewState="false" %>
<head>
<script runat="server" language="c#">
protected void Page_Load(object sender, EventArgs e)
{
if (HiddenField1.Value == String.Empty)
HiddenField1.Value = "111";
}
protected void Button1_Click(object sender, EventArgs e)
{ // HiddenField1.Value = (Convert.ToInt32(HiddenField1.Value) + 1).ToString();
Label1.Text = TextBox1.Text; }
protected void HiddenField1_ValueChanged(object sender, EventArgs e)
{ Response.Write("Changed." + DateTime.Now.ToString());
Response.Write(HiddenField1.Value);
Response.Write(TextBox1.Text); }
</script>
</head>
<body>
<form id="form1" runat="server"> <div>
<asp:HiddenField ID="HiddenField1" runat="server" OnValueChanged="HiddenField1_ValueChanged" />
</div>
<asp:Label ID= "Label1" runat="server" Text="Label"></asp:Label>
<br />
<asp:TextBox runat=server ID=TextBox1></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
</form>
</body >
</html>
利用HiddenFile 並結合ASP.NET2.0提供的「交叉Cross Page」頁面可以實現頁面資料的傳遞,該情況針對這樣的一種方案:
在一個註冊頁面裡,需要用戶輸入數據,由於備註一欄的數據可能很多,可以在新視窗可以利用類似FreeTextBox的控件讓用戶格式化文本,並在輸入完畢後,返回原始註冊頁面。關於這種情況,以後會介紹