使用JavaScript顯示MessageBox時的小技巧
當我們開發ASP.NET應用程式時,常常會需要透過JavaScript來顯示一些像是新增成功的提示訊息給使用者,而在ASP.NET的程式開發模型當中,想要於Server端以程式方式顯示Client端訊息,必須將JavaScript註冊到Client端,讓瀏覽器執行Alert等函式來跳出MessageBox,此時可以透過ClientScriptManager物件所提供的方法來完成上述需求,本文針對ClientScriptManager常用的RegisterClientScriptBlock和RegisterStartupScript函式進行說明,並試圖比較其差別。
【ClientScriptManager.RegisterClientScriptBlock】
MSDN指出ClientScriptManager.RegisterClientScriptBlock是"使用型別、索引鍵和指令碼常值,向 Page 物件註冊用戶端指令碼。"的方法,由此可知要使用RegisterClientScriptBlock方法必須傳入3個參數,以下為RegisterClientScriptBlock方法的簽名碼:
其中型別指的是要註冊的用戶端指令碼型別,通常會以Page的型別傳入,它與索引鍵共同用來唯一識別Client端Script。也就是當型別與索引鍵相同時,即使指令碼常值,也就是JavaScript的程式不同,也只會註冊第一個JavaScript到Client端。例如下列程式碼,連續註冊兩個Client端Script,其中型別(Page)與索引鍵(QuerySuccess)均相同,執行時將只會顯示【處理中】的訊息(如下圖)。
1: this.ClientScript.RegisterClientScriptBlock(this.GetType(), "QuerySuccess", "alert('處理中');", true);
2: this.ClientScript.RegisterClientScriptBlock(this.GetType(), "QuerySuccess", "alert('處理完畢');", true);
雖然實務上也許不會用到連續顯示兩個MessageBox,但要解決上述連續顯示兩個MessageBox,只要將型別或索引鍵其中一個改掉,讓兩段Alert不會重複即可,以下程式碼示範將索引鍵改成不同的鍵值,就可以正確顯示兩個MessageBox。
1: this.ClientScript.RegisterClientScriptBlock(this.GetType(), "QueryProcess", "alert('處理中');", true);
2: this.ClientScript.RegisterClientScriptBlock(this.GetType(), "QuerySuccess", "alert('處理完畢');", true);
此外,使用RegisterClientScriptBlock方法註冊Client端 Script來顯示MessageBox時,會出現如下圖左顯示的結果,也就是只出現一個對話視窗背景都是空白的,造成這個的原因是RegisterClientScriptBlock 方法會將指令碼區塊加入至呈現網頁頂端,而以alert顯示MessageBox屬於Modal Window,強制與使用者互動結束後才會繼續後面要執行的程式碼,檢視原始碼的結果如下圖右。
可以使用IsClientScriptBlockRegistered方法來判斷是否要執行的指令碼是否已經註冊過,以下程式碼範例用來示範加入IsClientScriptBlockRegistered判斷程式碼未註冊過才註冊:
1: if (!this.ClientScript.IsClientScriptBlockRegistered(this.GetType(),"QuerySuccess"))
2: this.ClientScript.RegisterClientScriptBlock(this.GetType(), "QuerySuccess", "alert('處理完畢');", true);
加入IsClientScriptBlockRegistered方法後,執行第一次alert('處理完畢')時,背景一樣會空白,但第二次執行時就不會。但這還是不夠完美,接下來我們將改用其他方式來修正這個問題。
【ClientScriptManager.RegisterStartupScript】
ClientScriptManager.RegisterStartupScript和ClientScriptManager.RegisterClientScriptBlock一樣是"使用型別、索引鍵和指令碼常值,向 Page 物件註冊用戶端指令碼。"的方法。差別在於RegisterStartupScript會在網頁完成載入之後,以及網頁 OnLoad 事件引發之前,來執行 RegisterStartupScript 方法所加入的指令碼區塊。因此就不會出現空白頁面的問題(如下圖右)。
同樣的可以在使用RegisterStartupScript註冊Script前,可以使用IsStartupScriptRegistered判斷是否註冊過,
【補充說明】
使用RegisterClientScriptBlock或RegisterStartupScript方法註冊Script到Client端時,不保證指令碼區塊可以根據其所註冊的順序來輸出。 如果要讓指令碼區塊依照順序執行,建議使用 StringBuilder 物件來集合所有要執行的指令碼,然後在單一用戶端指令碼區塊中註冊所有的指令碼。而且使用RegisterStartupScript或RegisterClientScriptBlock前建議先使用IsStartupScriptRegistered或IsClientScriptBlockRegistered來避免重複註冊,對於需要大量使用JavaScript的ASP.NET應用程式可以減少不必要的處理時間。
【參考資料】