第6回 ViewState
第4回中講到了給控制項添加屬性,現在我們在用戶端使用代碼訪問這些屬性看看效果如何。把虛擬目錄下的所有檔案清空,建立一個App_Code檔案夾,並在裡面建立一個“SimpleControl.cs”檔案,並輸入如下代碼:
例6-1代碼1:SimpleControl.cs代碼
using System;
using System.Web.UI;
namespace MyControl
{
public class LinksControl : Control
{
protected int _num=0;
public virtual int Num
{
get { return _num; }
set { _num=value; }
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write(Num.ToString());
}
}
}
這裡我們建立了一個很簡單的控制項,它有一個整型屬性Num,只是在Render中簡單地輸出了這個屬性的值。下面我們在aspx檔案中訪問這個屬性值。在虛擬目錄下建立一個Simple.aspx檔案,並輸入如下代碼:
例6-1代碼2:Simple.aspx代碼
<script runat="server" language="C#">
void Button1_Click(object sender, EventArgs e)
{
LC.Num++;
}
</script>
<%@Register TagPrefix="CG" Namespace="MyControl" %>
<html>
<body>
<form runat="server">
<CG:LinksControl ID="LC" runat="server" />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</form>
</body>
</html>
在aspx檔案中,添加了一個Button控制項,並在它的單擊事件中給我們剛才所定製的控制項的Num屬性加1。下面在瀏覽器中運行Simple.aspx檔案。這時,只出現一個數字0和一個按鈕。我們多次單擊按鈕,但數字始終為1,並沒有如我們所預期的那個不斷增加。這是為什麼呢?
其實大家應該都知道,用戶端向伺服器發出請求,伺服器做出響應後就不再維持此次請求用戶端的資訊。也就是說,我們在瀏覽器中輸入一個網址向伺服器發出請求,伺服器做出響應並執行個體化LinksControl類,在把響應資訊返回給用戶端後,控制項就被釋放了。這時我們在網頁上單擊了按鈕,再次向伺服器發出請求,伺服器會再次執行個體化LinksControl類以做出響應。也就是說每次單擊按鈕,所操作的都是LinksControl類的不同執行個體,屬性值並沒有得到儲存就很正常了。Web編程和WinForm編程模型真是天壤之別,真是讓人頭痛。
如何解決這個問題呢?ASP.NET中,把資訊回傳給伺服器時,提交了一個隱藏的ViewState控制項,這個控制項裡存放著頁面上的控制項的狀態。也就是說在點按鈕時,把當前LinksControl對象的Num屬性回傳給伺服器,伺服器再根據這個值產生新的頁面。
如何獲得這個回傳值呢?Control類晨有一個ViewState屬性,它是一個集合,使用ViewState[“Num”]就可以得到Num的回傳值。好,開啟SimpleControl.cs檔案,並對屬性的代碼稍做修改如下:
例6-2代碼1:SimpleControl.cs代碼
using System;
using System.Web.UI;
namespace MyControl
{
public class LinksControl : Control
{
public virtual int Num
{
get
{
return ViewState["Num"]!=null ?
(int)ViewState["Num"] : 0;
}
set
{
ViewState["Num"]=value;
}
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write(Num.ToString());
}
}
}
現在再運行Simple.aspx,多次點擊按鈕,看看數字是否已經隨著點擊次數增長?