全面介紹ASP.NET動態(tài)控件
我認(rèn)為感性認(rèn)識是理性認(rèn)識不可缺乏的基礎(chǔ)條件,所以在很理論性的解釋ASP.NET頁面生命周期之前,先通過一些大家可能都遇到過的例子給大家一個感性認(rèn)識。
ASP.NET動態(tài)控件遇到的第一類問題就是跨頁面生命周期時無法自動保存,你必須每次手動創(chuàng)建。舉個簡單的例子,例如現(xiàn)在我有一個DropDownList,有三個 ListItem,值分別是"0", "1", "2",在我設(shè)置了AutoPostBack之后,我希望SelectedIndexChanged時根據(jù)我選擇的ListItem數(shù)值動態(tài)創(chuàng)建相應(yīng)數(shù)量的TextBox,簡單的代碼如下:
- protectedvoiddropDownList_SelectedIndexChanged(objectsender,EventArgse)
- {
- for(inti=0;i<dropDownList.SelectedIndex;i++)
- {
- TextBoxdynamicTextBox=newTextBox();
- this.Form.Controls.Add(dynamicTextBox);
- }
- }
需要解釋一下的是,直接用dropDownList.SelectedIndex是為了省事,因為ListItem的值本身也就是從0開始的順序整數(shù)。
測試一下我們這個小小的ASP.NET程序有沒有問題,結(jié)果當(dāng)然是沒問題的,你選擇了哪個數(shù)值就真的會有相應(yīng)數(shù)量的TextBox出現(xiàn),好簡單哦!我們再扔一個Button到頁面上看看又會怎樣,這時候你就會發(fā)現(xiàn)如果通過點擊Button導(dǎo)致PostBack,那么動態(tài)創(chuàng)建的TextBox就沒掉了,看起來事情并不如我們期望的那么簡單。
“我們已經(jīng)知道這個問題啦,快點給出解決方案啦”——如果你急需要一個解決方案,請直接看本篇文章的最后幾段。我知道很多人是因為當(dāng)前有一個棘手的問題才來翻看這類文章的,但我也不能因此而忽視了另外一部分人的需求——他們希望由淺入深地了解這個問題,并且得到解決方案的同時得到完整解釋。
接下來我們繼續(xù)來看第二類問題,動態(tài)創(chuàng)建控件的事件觸發(fā)不正常。我們又來寫一段簡單代碼:
- protectedvoidPage_Load(objectsender,EventArgse)
- {
- TextBoxdynamicTextBox=newTestingTextBox();
- dynamicTextBox.ID="DynamicTextBox"
- dynamicTextBox.Text="InitData"
- dynamicTextBox.TextChanged+=newEventHandler(dynamicTextBox_TextChanged);
- this.Form.Controls.Add(dynamicTextBox);
- }
- voiddynamicTextBox_TextChanged(objectsender,EventArgse)
- {
- this.Trace.Write("DynamicTextBox","TextChanged");
- }
由于用到了Trace,測試的時候別忘記把Trace打開哦。
我們再扔一個LinkButton到頁面上,目的僅僅是為了觸發(fā) PostBack,然后看看事件是否正常。奇怪的事情發(fā)生了,在修改TextBox的值之前,無論怎么點那個LinkButton,一切都非常正常,TextChanged事件確實不發(fā)生。修改了TextBox的值之后點LinkButton,事情也還正常,TextChanged事件發(fā)生了。但之后就出問題了,無論你是否修改了TextBox的值,TextChanged總是在每一次PostBack時都被觸發(fā)。
這個問題很怪異對嗎?事件既非完全不觸發(fā),也非總是觸發(fā)。其實答案隱藏在我之前那篇《深入理解 ViewState》里面,去讀一讀那篇文章,或許你自己也能夠解釋為什么會這樣。
動態(tài)創(chuàng)建的控件或許還存在第三類、第四類問題,在此就不一一列舉了。我相信被動態(tài)控件問題困擾過的ASP.NET程序員絕對不少,而未遇到過此類問題的程序員看到上述兩個問題也未必能給出解決方案和正確解釋。
在提供問題的解決方案之前首先要說明一點,作為ASP.NET程序員的你需要在某一時刻某一地方讓控件動態(tài)出現(xiàn)時,就立即在該處寫代碼動態(tài)創(chuàng)建并添加控件,這往往都是錯誤的做法。正確的做法是向后退三步再抬頭看,這時候你看到的就不是你要讓控件動態(tài)出現(xiàn)的那一個準(zhǔn)確的時刻和地方,你應(yīng)該看到ASP.NET頁面生命周期的全貌,接著你就應(yīng)該清楚你的代碼該加去哪里了。
好了,是時候給出最直接的解決方案了,唯一的解決方案就是讓你看清楚ASP.NET頁面生命周期的全貌,而其中最佳的入門方式就是學(xué)習(xí)控件設(shè)計。雖然上面把ASP.NET動態(tài)控件說成一個復(fù)雜的問題,然而大家天天都在用動態(tài)控件,只不過ASP.NET動態(tài)控件已經(jīng)被封裝到一個靜態(tài)控件里了。例如復(fù)雜的GridView控件,它會自動根據(jù)每一列的性質(zhì)來生成對應(yīng)控件,如果是模板列還要分析模板中的內(nèi)容來生成模板中定義的控件,這些控件都算是動態(tài)控件,為什么PostBack不會讓他們自動消失,為什么為它們添加的事件從來不會錯誤觸發(fā),在你學(xué)習(xí)完控件設(shè)計之后就會一清二楚。
關(guān)于控件設(shè)計,我推薦大家買Wrox(樂思)的書來看,是以控件設(shè)計為主題的那兩本,不會很厚,很快能看完。如果你在使用的是ASP.NET 1.x,或者你一定要看中文版的書,那么ASP.NET服務(wù)器控件高級編程將是一本很適合你的書。至于ASP.NET 2.0的則有Professional ASP.NET 2.0 Server Control and Component Development,英文版今年8月才發(fā)布,根據(jù)清華出版社的慣例至少要等半年才可能有對應(yīng)中文版。
既然連解決方案都給出了,這個系列的文章繼續(xù)寫下去還有什么意義嗎?書上能給你的只是一個臨摹著去做就不會出錯的模式,以及一個聽起來很合理的解釋。到底為什么臨摹這種模式去做就符合ASP.NET的大模式(主要是編譯模型和頁面生命周期),ASP.NET的大模式到底是怎樣的,這就是我接下來要寫的東西。
【編輯推薦】