介紹ASP.NET頁面生命周期
ASP.NET頁面生命周期
在面對此類問題的時候,首先問問自己控件的數量,如果數量不多,直接通過設置控件的Visible屬性解決問題就是了。這也就是說,把可能要顯示的控件都聲明為Visible="false",然后在代碼中判斷當前應該將哪個顯示出來。
如果控件比較多,然而還是能分組的,同一時間僅僅顯示其中的一組,那么你應該考慮使用MultiView,這樣你的工作將會輕松不少。事實上,能夠使用 MultiView解決的,都應該優先考慮使用MultiView解決,這比起自己控制哪一個控件顯示哪一個控件隱藏要方便多了。其實MultiView 所做的,也就是幫你控制控件的顯示與隱藏。
這樣做的性能如何呢?我們關注兩方面的問題,一方面是服務器端執行的資源消耗,另一方面是傳輸的帶寬消耗。我們先來看看服務器端執行的資源消耗吧,我們最常見的消耗應該就是數據控件操作數據庫時的消耗了。在ASP.NET 1.x時代,我們沒有數據源控件,所以必須手動進行DataBind(),這也就是說如果不手動執行DataBind()的話就不會進行任何數據操作,因此只要我們記得在數據控件不顯示的時候也不要讓它執行DataBind()就是了,那樣就不會有性能損失。在ASP.NET 2.0當中,使用數據源控件的話數據控件是會自動DataBind()的,這時候會造成控件隱藏時的資源消耗呢?事實上是不會的,數據控件即使已經定義了 DataSourceID屬性,它也僅僅在自己***次可見時才進行自動DataBind()。如果數據控件的狀態是隱藏的(包括使用MultiView隱藏),它就不會自動進行DataBind()。因此,在ASP.NET 2.0中使用數據源控件以及MultiView之后其底層過程還是和ASP.NET 1.x手動操作的一樣,就是少寫一些代碼而已。
我們接著來看看帶寬消耗如何,因為隱藏的控件不輸出任何的HTML,因此帶寬消耗就是指ViewState了。控件隱藏后,ViewState是不變的,因此隱藏控件確實比完全不加載控件造成了更多的資源消耗,換取的是該控件的狀態得以保存。一般來說,簡單控件隱藏后多出來幾十字節的ViewState是可以忽略不計的,整個頁面中HTML縮進所需的空格也都幾十上百字節了;但如果是復雜控件,擁有大量的ViewState,這時候你真的應該考慮動態加載了。
總的來說,面對這類問題時首先判斷顯示隱藏控件的邏輯是否復雜,控件本身是否復雜。如果是比較簡單的情況,則直接使用 MultiView解決就是了。如果是復雜的情況,那就應該考慮自己使用控件將此邏輯封裝在內,而不是直接在頁面上暴露這些復雜性。關于封裝控件的問題,在下一篇文章中再討論,因此我們繼續看下一類問題。
既不確定類型也不確定數量的控件
有時候我們面對前面兩類問題都有清晰的思路,但是面對復合問題就感覺很混亂了。例如還是一個調查問卷的顯示,數據來自XML,問題類型包括單選和多選,每一道問題的選項個數也不確定,這時候怎么辦呢?foreach嵌套foreach,外層迭代問題內層迭代選項,逐個CheckBox/RadioButton來生成?
這時候我們需要的是把問題分而治之逐個擊破的思想。既然是上述兩類問題的嵌套,我們就應該能夠通過嵌套對應的解決方案來實現。對于這個調查問卷的例子,我們可以用Repeater來迭代問題,先把這個定下來,再考慮模板里面怎么做。模板里面需要顯示的是一個不確定類型的問題,因此模板里面放一個 MutliView,把問題類型的表達式綁定到其ActiveViewIndex屬性上,例如單選題就是0多選題就是1。然后MultiView里面的兩個View各自嵌套一個Repeater,第0個Repeater迭代選項并顯示為RadioButton,第1個Repeater迭代選項并顯示為 CheckBox。就這樣就完成了,我們沒寫任何一行后臺代碼,也沒有動態創建任何控件。
然后我們來分析一下這個解決方案的性能。對比起動態創建控件,它所使用的控件確實是多了一倍,因為一道問題同時創建了兩組選項,一組單選一組多選,只不過其中一組被隱藏了。然而隱藏掉的那一組唯一的服務器端資源消耗就是創建以及綁定,它們不輸出任何的HTML,因為它們的值不會被改變所以也不會輸出任何的ViewState,并且它們也不會觸發任何事件,因此在對性能沒有特別要求的情況下這樣的性能損失還是可以接受的。至少,這比起你自己去研究ASP.NET頁面生命周期然后自己寫一大段代碼來實現動態加載控件要好多了。
問題與實驗
本系列上一篇文章的問題與實驗一直沒有解答,現在給出參考答案如下:
1.為Page增加一個ShowCheckBox的屬性:
- bool ShowCheckBox {
- get { return (ViewState["ShowCheckBox"] == null) ?
false : (bool)ViewState["ShowCheckBox"]; }- set { ViewState["ShowCheckBox"] = value; }
- }
在OnLoad的時候檢測ShowCheckBox屬性,如果為true則添加上該CheckBox控件。在Button的 OnClick事件中,設置ShowCheckBox為true,并添加上CheckBox。記得這兩處創建的CheckBox必須擁有一致的ID屬性。
2. 這是為了讓ICallbackEventHandler的處理模型符合ASP.NET頁面生命周期的模型。雖然Callback發生的時候,ASP.NET頁面生命周期已經與PostBack不同,然而ICallbackEventHandler還是讓Callback模仿了PostBack的頁面生命周期。RaiseCallbackEvent相當于PostBack的Raise PostBackEvent階段,GetCallbackResult相當于PostBack的PreRender階段。前者負責事件響應,后者負責生成返回客戶端的HTML代碼。
這次想和大家討論的問題是,你覺得你是***主義者嗎?面對上面的調查問卷需求,你會選擇我所說的Repeater套MultiView再套Repeater的做法,從而避免寫任何一行后臺代碼,還是會選擇自己封裝一個控件動態創建所有控件,避免任何不必要的性能損失?
【編輯推薦】

















