ASP.NET組件設計之ASP.NET Timer淺析
ASP.NET組件設計之ASP.NET Timer一、思考組件需求
在網(wǎng)頁上編寫一個Timer組件,首先得解決這個問題:如何讓網(wǎng)頁定時Post回Server端。 正常情況下這個動作是由用戶按下某個按鈕后觸發(fā)的,但Timer組件的需求是自動在特定時間觸發(fā),例如設計者設定在每5秒產(chǎn)生一個Post動作,網(wǎng)頁就得每5秒做出一個Post動作,這該如何完成呢?事實上,這可以通過Javascript提供的一個setTimeout函數(shù)來完成,只要運用此函數(shù)每5秒調(diào)用一次由ASP.NET產(chǎn)生的_doPostBack函數(shù)即可達到定時自動Post的需求,下面是setTimeout函數(shù)的原型。
- setTimeout(﹤function﹥,﹤interval﹥);
***個參數(shù)是當Timeout時間到時所調(diào)用的函數(shù),第二個是Timeout時間的長度,單位是毫秒(millisecond)。解決網(wǎng)頁定時自動Post的問題后,接著就是Server端如何接收這個信息的問題,答案就是Post-Back機制,只要實現(xiàn)此機制,組件就能在網(wǎng)頁自動Post后取得主控權(quán),并引發(fā)用戶所掛載的事件函數(shù)。
ASP.NET組件設計之ASP.NET Timer二、實現(xiàn)Post-Back與繪制JavaScript
現(xiàn)在我們面臨兩個問題:***是組件的基類選擇。由于WebTimer屬于不可視組件,并不需要任何外觀睥屬性,所以自然是繼承自Control類;第二是WebTimer必須實現(xiàn)Post-Back接口,宋才能在網(wǎng)頁自動Post取得主控權(quán)后觸發(fā)用戶所掛載的事件函數(shù)。 下面是WebTimer處理Post-Back機制的部分程序代碼
- public class WebTimer:Control,IPostBackEventHandler
- {
- …………
- IPostBackEventHandler implements#region IPostBackEventHandler implements
- void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
- {
- OnTimer(EventArgs.Empty);
- }
- #endregion
- …………
- }
由程序易知,WebTimer繼承自Control類,同時實現(xiàn)了IPostBackEventHandler接口。當組件實現(xiàn)了該接口之后,Post-Back發(fā)生時Page對象會一一調(diào)用已注冊參與Post-Back運作組件的IPostBackEventHandler.RaisePostBackEvent函數(shù),此處WebTimer組件調(diào)用了OnTimer函數(shù)將控制權(quán)轉(zhuǎn)交給設計者所綁定的事件上,下面是OnTimer函數(shù)及事件處理部分的代碼:
- private static readonly object EventTimer = new object();
- …………
- Events#region Events
- public event EventHandler Timer
- {
- add{Events.AddHandler(EventTimer,value);}
- remove{Events.RemoveHandler(EventTimer,value);}
- }
- #endregion
- event handler functions#region event handler functions
- protected virtual void OnTimer(EventArgs e)
- {
- EventHandler timerHandler = (EventHandler)Events[EventTimer];
- if(null != timerHandler)
- {
- timerHandler(this,e);
- }
- }
- #endregion
接下來要做的就是繪制JavaScript函數(shù)。在這之前,還有一件很重要的事,那就是繪制默認的_doPostBack函數(shù)。默認情況下Page對象為了節(jié)省帶寬,并不是每次都繪制此函數(shù)。只有在某個組件明確調(diào)用Page.GetPostBackEventReference或Page.GetPostBackClientHyperlink其中的一個函數(shù)時,_doPostBack函數(shù)才會被繪制到網(wǎng)頁中。因此,WebTimer組件必須得調(diào)用Page.GetPostBackEventReference或是Page.GetPostBackClientHyperlink函數(shù),但是在哪里調(diào)用呢?Render函數(shù)?不行!此時Page對象已經(jīng)進入繪制狀態(tài),在此時調(diào)用Page對象的任何函數(shù)都已經(jīng)太遲了,所以***的地方是調(diào)用OnPreRender函數(shù),下面是相關代碼:
- protected override void OnPreRender(EventArgs e)
- {
- base.OnPreRender(e);
- //call this method to ensure that the _doPostBack method will be called
- Page.ClientScript.GetPostBackEventReference(this,"");
- }
接下來就是編寫JavaScript函數(shù)并在Render函數(shù)中繪制相關動作:
- Utility functions#region Utility functions
- private string BuildJavaScript()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("\n﹤script language=\"javascript\"﹥\n ﹤!-- ");
- sb.AppendFormat("\n setTimeout(\"{0}\",{1});",
- new object[]{this.Page.GetPostBackEventReference(this),interval.ToString()});
- sb.Append("\n //--﹥\n﹤/script﹥");
- return sb.ToString();
- }
- #endregion
- protected override void Render(HtmlTextWriter writer)
- {
- /**//*to ensure that this component is in the "runat=server" HtmlForm,
- or there'll be no Post-Back event,as a result that this component will be of no avail
- */
- if(null != Page)
- Page.VerifyRenderingInServerForm(this);
- if(enabled)
- writer.Write(BuildJavaScript());
- }
除了Render函數(shù)之外,程序中尚用到兩個函數(shù):Page.VerifyRenderingInServerForm函數(shù)用來確認組件位于標記為”runat=server”的HtmlForm控件中,假如組件并非位于此類的HtmlForm中,那么也就沒有Post-Back帶傷,WebTimer組件自然也就沒有作用了。另外一個是BuildJavaScript,此函數(shù)將之前所討論的JavaScript函數(shù)setTimeout配合用戶所設定的時間繪出。
有一點要指出來的是,在.net 2.0里面會有個警告提示System.Web.UI.Page.GetPostBackEventReference(System.Web.UI.Control)已過時,建議用ClientScript.GetPostBackEventReference來代替,新的函數(shù)重載了四次,但是沒有一個參數(shù)的,現(xiàn)在還不知道怎么改,有知道的希望能指出來!
ASP.NET組件設計之ASP.NET Timer的基本情況就向你介紹到這里,希望對你學習有所幫助。
【編輯推薦】