雖然平時也都經常用到,.net+用戶端指令碼,從 ASP.NET 伺服器控制項插入用戶端指令碼

來源:互聯網
上載者:User

從 ASP.NET 伺服器控制項插入用戶端指令碼
Scott Mitchell

2003 年 8 月

適用於:
    Microsoft? ASP.NET

前提條件:本文假設讀者熟悉 ASP.NET。

難度: 2

摘要:儘管從技術角度講,ASP.NET 伺服器控制項的所有功能都可以在伺服器端執行,但通常情況下通過添加用戶端指令碼可以大大增強伺服器控制項的可用性。本文將探討伺服器控制項發送用戶端指令碼的兩種方法,還將構建兩個使用這些技術的伺服器控制項:
PopupGreeting
,一個在首次載入的 Web 頁面上顯示帶有特定訊息的用戶端強制回應對話方塊的伺服器控制項;
ConfirmButton
,一個增強 Button Web 控制項,如果使用者點擊此按鈕,則在發回 Web Form前向使用者顯示一個 JavaScript
confirm()
 的對話方塊。(本文包含一些指向英文網站的連結。)

下載 InjectingClientSideScript.msi。

目錄
簡介
使用 RegisterStartupScript() 和 RegisterClientScriptBlock() 添加用戶端指令碼塊
探討 IsStartupScriptRegistered() 和 IsClientScriptBlockRegistered()
從 ASP.NET 伺服器控制項發送用戶端指令碼塊
發送 ASP.NET 伺服器 Web 控制項的 HTML 屬性
小結

簡介
儘管從技術角度講,Microsoft? ASP.NET 伺服器控制項的所有功能都可以在伺服器端執行,但通常情況下通過添加用戶端指令碼可以大大增強伺服器控制項的可用性。例如,ASP.NET 驗證 Web 控制項可以在伺服器端執行所有的驗證檢查。但是,對於高版本瀏覽器,驗證 Web 控制項也會發送用戶端指令碼,以在用戶端進行驗證。這就是說,這些瀏覽器的使用者可以獲得響應效果更好的動態體驗。

在開發 ASP.NET 伺服器控制項時,您不妨問問自己,如何才能通過使用用戶端指令碼來增強可用性。一旦找到可行的方案,其他要做的就是增強伺服器控制項的功能,以使其發送合適的用戶端指令碼。

ASP.NET 伺服器控制項可以發送兩種用戶端指令碼:

用戶端指令碼塊
用戶端 HTML 屬性
用戶端指令碼塊通常是用 JavaScript 編寫的,其中通常包含在發生特定的用戶端事件時執行的函數。用戶端 HTML 屬性提供將用戶端事件與用戶端指令碼聯絡在一起的方法。例如,以下的 HTML 頁面中包含了用戶端指令碼塊,指令碼塊中包含了名為
doClick()
 的函數。該頁面同時還包含一個按鈕(通過
<input>
 HTML 元素建立),這個按鈕的
onclick
 屬性與
doClick()
 函數綁定。也就是說,只要使用者單擊該按鈕,就開始執行
doClick()
 函數中的用戶端代碼。在本樣本中,將顯示一個彈出式對話方塊(圖 1)。

<html>
  <body>
    <form>
      <script language="JavaScript">
      <!--
         function doClick() {
            alert("You clicked me!");
         }
      // -->
      </script>

      <input type="button" onclick="doClick()" value="Click Me!" />
    </form>
  </body>
</html>

圖 1 是單擊“Click Me!”按鈕時 HTML 頁面的螢幕快照。

 

圖 1:單擊“Click Me!”按鈕時顯示的彈出式對話方塊

對於以上 HTML 頁面中的用戶端指令碼,有幾點值得注意。首先,用戶端指令碼塊包含在 HTML 注釋(
<!--
 和
-->
)中。之所以這樣,是因為如果不將指令碼塊放入 HTML 注釋中,那些不能識別指令碼的舊式瀏覽器就會顯示
<script>
 塊的內容。此外,還要注意,指令碼塊中 HTML 注釋的結束標記前有一個 JavaScript 注釋,即
//
。這是因為舊版本的 Netscape 在遇到
-->
 時,會拋出 JavaScript 分析異常,因此必須將其注釋掉。幸運的是,現代的瀏覽器已不需要這一額外操作,所以在為 Intranet 或其他由瀏覽器控制的環境開發 Web 頁面時,您就不必採取此類預防措施了。

如果您對用戶端指令碼不是很熟悉,alert(string) 函數的作用就是顯示一個模式彈出式對話方塊,對話方塊中包含的訊息由 string 參數指定。所有 HTML 元素都有若干個可以綁定一段用戶端 JavaScript 代碼的用戶端屬性(例如,
onclick

onmouseover

onmouseout

onfocus
 和
onblur
 等等)。例如,在上面的 HTML 頁面中,
<input>
 元素的
onclick
 屬性綁定到
doClick()
 函數,因此在單擊該按鈕時將執行
doClick()
 函數。有關 JavaScript 事件及其關聯的 HTML 屬性的列表,請參閱 Introduction to Dynamic HTML 一文。有關用戶端 JavaScript 的詳細資料,請參閱 HTML and Dynamic HTML 一文。

在本文中,我們將學習如何在 ASP.NET 伺服器控制項中發送用戶端指令碼塊和 HTML 元素屬性。我們首先討論如何使用
System.Web.UI.Page
 類中的兩個方法來向 ASP.NET Web 頁面添加用戶端指令碼塊,這兩個方法是
RegisterStartupScript()
 和
RegisterClientScriptBlock()
。掌握這一知識後,我們將構建一個簡單的伺服器控制項,讓這個控制項在每次載入頁面時顯示一個用戶端彈出式對話方塊。之後,我們再來瞭解如何將 HTML 屬性添加到 ASP.NET 伺服器控制項的 HTML 元素。最後,我們將歸納所有知識,實際構建一個 ConfirmButton Web 控制項,當單擊這個控制項時,將向使用者提示一個對話方塊,詢問使用者是否要繼續。

使用 RegisterStartupScript() 和 RegisterClientScriptBlock() 添加用戶端指令碼塊
System.Web.UI.Page 類包含的兩個方法可以將用戶端指令碼代碼發送到由 ASP.NET Web 頁面提供的 HTML 中:

RegisterStartupScript(key, script)
RegisterClientScriptBlock(key, script)
這兩個方法都接受兩個字串作為輸入。第二個參數 script 是要插入到頁面中的用戶端指令碼,包括
<script>
 的起始標記和終止標記。第一個參數 key 是插入的用戶端指令碼的唯一識別碼。

這兩個方法唯一的不同之處在於從“何處”發送指令碼塊。
RegisterClientScriptBlock()
 在 Web Form的開始處(緊接著
<form runat="server">
 標識之後)發送指令碼塊,而
RegisterStartupScript()
 在 Web Form的結尾處(在
</form>
 標識之前)發送指令碼塊。

為什麼會有兩種不同的方法來發送用戶端指令碼?要更好地瞭解這一點,我們必須首先瞭解,用戶端指令碼可以分為兩類:一類是在載入頁面後立即啟動並執行代碼,一類是在發生某些用戶端事件時才啟動並執行代碼。前者的常見樣本是將焦點設定到文字框的用戶端代碼。例如,當您訪問 Google 時,在頁面載入後就會執行一小段用戶端代碼,以自動將焦點設定到搜尋文字框。

以下是後一類代碼(為響應用戶端事件而啟動並執行代碼)的樣本。具體而言,在該樣本中,單擊按鈕時將顯示一個彈出式對話方塊:

<html>
  <body>
    <form>
      <script language="JavaScript">
      <!--
        function displayPopup() {
            alert("Hello, world.");
        }
      // -->
      </script>

      <input type="button" value="Click Me!" onclick="displayPopup()" />
    </form>
  </body>
</html>

在這段代碼中,
<input>
 標記中的
onclick="displayPopup()"
 用於指明在單擊按鈕時,JavaScript 函數
displayPopup()
 應該運行。

RegisterStartupScript()
 方法可用於添加要在載入頁面後啟動並執行指令碼塊。通過這種方法添加的指令碼塊位於 Web Form的結尾處,因為必須在指令碼運行前定義指令碼要修改的 HTML 元素。也就是說,如果您要使用用戶端指令碼將焦點設定到文字框,必須確保文字框的 HTML 標籤位於設定該文字框的焦點的指令碼之前。例如,下面的 HTML 將顯示一個文字框,並將焦點設定到該文字框:

<input type="text" id="myTextBox" />

<script language="JavaScript">
<!--
   document.getElementById("myTextBox").focus();
// -->
</script>

相反,以下 HTML 不會將焦點設定到文字框,因為文字框是在指令碼塊“之後”定義的:

<script language="JavaScript">
<!--
   document.getElementById("myTextBox").focus();
// -->
</script>

<input type="text" id="myTextBox" />

因此,
RegisterStartupScript()
 方法將
<script>
 塊置於 Web Form的結尾處,以保證在執行用戶端指令碼之前已聲明 Web Form中的所有 HTML 元素。

RegisterClientScriptBlock()
 方法用於為響應用戶端事件而執行的指令碼代碼。通過此方法發送的指令碼塊位於 Web 頁面的開始處,因為這種方法不要求將指令碼塊置於所有 HTML 元素之後。

探討 IsStartupScriptRegistered() 和 IsClientScriptBlockRegistered()

RegisterStartupScript()
 和
RegisterClientScriptBlock()
 方法之外,
Page
 類還包含兩個在發送用戶端指令碼時常用的輔助方法:

IsStartupScriptRegistered(key)
IsClientScriptBlockRegistered(key)
如上所述,在使用
RegisterStartupScript()
 或
RegisterClientScriptBlock()
 插入用戶端指令碼塊時,提供了一個唯一標識指令碼塊的關鍵字。這兩個方法都接受一個輸入(字串 key),並返回一個布爾值,以指示帶有指定關鍵字的指令碼塊是否已添加到頁面中。具體地說,如果帶有特定 key 的指令碼塊已經註冊,這些方法將返回 True,否則將返回 False。

要瞭解如何使用這兩個方法,可以看一看 ASP.NET 驗證 Web 控制項,如 RequiredFieldValidator、RegularExpressionValidator 等等。這些控制項都會用到一個常用的驗證 JavaScript 檔案 (
WebValidation.js
),該檔案位於 ASP.NET Web 應用程式的
aspnet_client/system_web/版本號碼
 目錄中。因此,所有這些控制項都會發送相同的指令碼塊,這個指令碼塊將調用在
WebValidation.js
 檔案中定義的相應的 JavaScript 函數,以啟動用戶端的驗證過程。要完成這個過程,這些控制項會使用
Page
 類的
RegisterClientScriptBlock()
 方法,並使用關鍵字
ValidatorIncludeScript

接下來要考慮的是,如果一個 ASP.NET Web 頁面中包含多個驗證 Web 控制項,會出現什麼情況呢?所有這些 Web 控制項都要使用相同的關鍵字發送相同的指令碼塊。如果使用這個關鍵字調用兩次
RegisterClientScriptBlock()
 或
RegisterStartupScript()
 方法,則第二次調用會被認為是複製指令碼塊而被忽略。因此,即使一個 Web 頁面上有多個驗證控制項,也只是發送一個公用指令碼塊的執行個體。但是,請注意,除第一個控制項之外的其他所有驗證 Web 控制項都會構建要發送的公用用戶端指令碼,而這隻是在浪費時間。

這時就應該使用
IsClientScriptBlock()
 和
IsStartupScript()
 方法。這樣一來,驗證 Web 控制項就不會先花時間構建要發送的用戶端代碼,而是先檢查是否已經存在使用關鍵字
ValidatorIncludeScript
 註冊的指令碼。如果存在,控制項就會放棄構建用戶端指令碼塊,因為指令碼塊已經由頁面上的其他驗證控制項構建了。

因此,每次構建用戶端指令碼時,應該首先調用
IsClientScriptBlock()
 或
IsStartupScript()
 方法,以確定是否需要產生用戶端指令碼。在下面一節,我們將看到一些樣本,在這些樣本中,
IsClientScriptBlock()

IsStartupScript()
 方法先後與
RegisterClientScriptBlock()
 和
RegisterStartupScript()
 方法結合使用。

從 ASP.NET 伺服器控制項發送用戶端指令碼塊
請記住,
RegisterStartupScript()
 和
RegisterClientScriptBlock()
 方法是
System.Web.UI.Page
 類的方法。幸運的是,可以容易地從 ASP.NET 伺服器控制項調用這兩個方法,因為
System.Web.UI.Control
 類(所有 ASP.NET 伺服器控制項都直接或間接地從這個類匯出)有一個包含對
Page
 執行個體的引用的
Page
 屬性,而這個
Page
 執行個體包含伺服器控制項。因此,要從 ASP.NET 伺服器控制項添加用戶端指令碼塊,您只需使用下面的文法:

this.Page.RegisterClientScriptBlock(key, script);
通常,添加用戶端指令碼塊這個任務會使用
OnPreRender()
 方法來處理,這個方法在控制項生命週期的預呈現階段執行。

讓我們建立一個只顯示用戶端彈出式對話方塊的 ASP.NET 伺服器控制項。此樣本將說明構建一個發送用戶端指令碼的控制項是很容易的。

首先,在 Microsoft? Visual Studio? .NET 中建立一個新的 Web Control Library(Web 控制項陳列庫)項目。這將建立一個只有一個類的新項目,這個類從
System.Web.UI.WebControls.WebControl
 匯出。但是,我們希望這個類從
System.Web.UI.Control
 類匯出。為什麼呢?因為
WebControl
 類用於支援顯示為 HTML 元素的伺服器控制項,而
Control
 類則用於不會顯示為 HTML 元素的伺服器控制項。

大多數內建的 ASP.NET 伺服器控制項都會發送一個 HTML 元素。例如,TextBox Web 控制項發送一個
<input>
 元素,其類型屬性設定為 text;DataGrid Web 控制項發送一個
<table>
 元素,為每條要顯示的記錄發送
<tr>
 元素,為每個欄位發送
<td>
 列。但是,不是所有的控制項都需要發送 HTML 元素。例如,Literal 控制項只是按原樣輸出它的 Text 屬性,而不將這個屬性放在 HTML 元素中。同樣,Repeater 也不將其輸出放在 HTML 元素中。那些顯示為 HTML 元素的伺服器控制項,如 TextBox、Button、DataGrid 等等,是從
System.Web.UI.WebControls.WebControl
 類匯出的,而那些不產生 HTML 元素的控制項,如 Literal、Repeater 等,是從
System.Web.UI.Control
 類匯出的。

既然我們要建立的伺服器控制項不可見(它只是發送一個顯示快顯控制項的用戶端指令碼塊),這個控制項最好從
System.Web.UI.Control
 匯出,而不是從
System.Web.UI.WebControls.WebControl
 匯出。

這個控制項只需要兩個屬性:

PopupMessage
 - 表示要在彈出式對話方塊中顯示的訊息的字串。
Enabled
 - 表示是否啟用控制項的布爾值。如果啟用控制項,則顯示彈出式對話方塊,否則不顯示。(必須添加一個
Enabled
 屬性,是因為匯出該控制項的
Control
 類不包括
Enabled
 屬性,此屬性只是隱含地由那些從
WebControl
 匯出的控制項使用。)
除了這兩種屬性之外,我們需要覆蓋
OnPreRender()
 方法。在這裡,我們需要調用
RegisterStartupScript()
,並傳遞控制項唯一的關鍵字和恰當的用戶端指令碼以顯示彈出式對話方塊。這個類的完整代碼如下所示:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace ClientSideScript
{
   /// <summary>
   /// WebCustomControl1 的摘要描述。
   /// </summary>
   [DefaultProperty("Text"),
      ToolboxData("<{0}:PopupGreeting runat=server></{0}:PopupGreeting>")]
   public class PopupGreeting : System.Web.UI.Control
   {
      [Bindable(true),
         Category("Appearance"),
         DefaultValue("")]
      public string PopupMessage
      {
         get
         {
            // 檢查 ViewState 中是否存在該項目
            object popupMessage = this.ViewState["PopupMessage"];
            if (popupMessage != null)
               return this.ViewState["PopupMessage"].ToString();
            else
               return "Welcome to my Web site!";
         }

         set
         {
            // 指定 ViewState 變數
            ViewState["PopupMessage"] = value;
         }
      }

      [Bindable(true),
      Category("Appearance"),
      DefaultValue("")]
      public bool Enabled
      {
         get
         {
            // 檢查 ViewState 中是否存在該項目
            object enabled = this.ViewState["Enabled"];
            if (enabled != null)
               return (bool) this.ViewState["Enabled"];
            else
               return true;
         }

         set
         {
            // 指定 ViewState 變數
            ViewState["Enabled"] = value;
         }
      }

      protected override void OnPreRender(EventArgs e)
      {
         base.OnPreRender(e);

string scriptKey = "intoPopupMessage:" + this.UniqueID;

         if (!Page.IsStartupScriptRegistered(scriptKey) && this.Enabled &&
                      !Page.IsPostBack)
         {
            string scriptBlock =
               @"<script language=""JavaScript"">
               <!--
                  alert(""%%POPUP_MESSAGE%%"");
               // -->
               </script>";
            scriptBlock = scriptBlock.Replace("%%POPUP_MESSAGE%%", this.PopupMessage);

            Page.RegisterStartupScript(scriptKey, scriptBlock);
         }
      }
   }
}

請記住下面兩件事:首先,
Enabled
 和
PopupMessage
 屬性儲存在
ViewState
 中,這樣在回傳時這些值可以始終保持一致; 其次,在
OnPreRender()
 方法中,用於指令碼塊的關鍵字是文本
intoPopupMessage:
 加上控制項的
UniqueID
 屬性。如果使用一個硬式編碼關鍵字,則當頁面中有多個控制項時,只有第一個控制項能夠註冊其指令碼塊,因此只顯示一個彈出式對話方塊。通過在指令碼塊關鍵字中使用
UniqueID
,就能保證該控制項的每個執行個體都能擷取其指令碼塊。

在註冊指令碼塊之前,代碼首先檢查三個條件:

沒有使用同一關鍵字註冊的指令碼。這當然是不可能的,因為每個控制項執行個體都應該有一個 UniqueID 屬性值。但是,不妨先練習使用
IsStartupScriptRegistered()
 方法,然後再花時間建立和註冊啟動指令碼。
控制項的 Enabled 屬性為 True。
頁面沒有被回傳。這段代碼只允許彈出式對話方塊在第一次載入頁面時顯示,而不是在每次回傳頁面時都顯示。我們還可以增添更為靈活的功能,即為該控制項添加一個布爾屬性,以允許使用者指定是否在回傳時也產生彈出式對話方塊。
如果滿足這三個條件,則指令碼被指定,並且
PopupMessage
 屬性值被插入到指令碼中適當的位置。最後,調用
Page
 屬性的
RegisterStartupScript()
 方法,傳入關鍵字及指令碼代碼。

PopupGreeting 代碼可以從本文結尾處提供的下載中獲得。該下載包括名為 ClientSideControlsAndTester 的 Visual Studio .NET 解決方案,其中包含兩個項目:

ClientSideControls,包含 PopupGreeting 伺服器控制項
ClientSideTester,包括一個為測試 ClientSideControls 而設計的 ASP.NET Web 應用程式
ClientSideControls 項目編譯後的程式集名為
ClientSideControls.dll
。要在您自己的 ASP.NET Web 應用程式中使用 PopupGreeting 伺服器控制項,請將
ClientSideControls.dll
 檔案添加到您的 Web 應用程式的引用中。然後,在設計器中,按右鍵 Toolbox(工具箱)並選擇“Add/Remove Items . . .”(添加/刪除項),再次選擇
ClientSideControls.dll
 檔案。這樣就向 Toolbox(工具箱)中添加了名為 PopupGreeting 的新項。然後,您可以從 Toolbox(工具箱)將該控制項拖到設計器中。

圖 2 顯示了 PopupGreeting 控制項添加到 Toolbox(工具箱)並添加到設計器後,Visual Studio .NET 的螢幕快照。Toolbox(工具箱)中的 PopupGreeting 控制項用紅色線圈出,設計器中的 PopupGreeting 輸出用藍色線圈出,在螢幕快照右側的“Properties”(屬性)窗格中可以查看 PopupGreeting 的屬性。

 

圖 2:PopupGreeting 伺服器控制項已添加到 ASP.NET Web Form頁面

發送 ASP.NET 伺服器 Web 控制項的 HTML 屬性
如上所述,有兩種方法可以通過伺服器控制項發送用戶端指令碼:

通過使用用戶端指令碼塊
通過 HTML 元素屬性
在上一節中,我們探討了如何使用
Page
 類的
RegisterStartupScript()
 和
RegisterClientScriptBlock()
 方法向 ASP.NET Web 頁面添加用戶端指令碼塊。在最後這一節,我們瞭解如何將 HTML 元素屬性添加到伺服器控制項的 HTML 元素。

在開始之前,請注意這種方法通常只適用於從
System.Web.UI.WebControls.WebControl
 類匯出的伺服器控制項,因為從這個類匯出的控制項會發送某些 HTML 元素。不發送 HTML 元素的伺服器控制項(如上一節中的 PopupGreeting 伺服器控制項),則不必寫出 HTML 元素屬性,因為這些控制項運行時不會寫出 HTML 元素。

WebControl
 類包含一個將 HTML 元素屬性添加到由 Web 控制項發出的 HTML 元素的方法。該方法稱為
AddAttributesToRender()
,它只有一個輸入參數,即
HtmlTextWriter
 的執行個體。要向 Web 控制項添加 HTML 屬性,您可以使用
HtmlTextWriter
 的以下兩個方法之一:

AddAttribute()
AddStyleAttribute()
AddAttribute()
 方法用於將
title

class

style
 和
onclick
 等 HTML 屬性添加到 HTML 元素。
AddStyleAttribute()
 用於將樣式設定添加到 HTML 元素,如
background-color

color
 和
font-size
 等。

AddAttribute()
 有幾個重載表單,但在代碼中,我們將使用以下表單:
AddAttribute(HtmlTextWriterAttribute, value)
。第一個參數,即 HtmlTextWriterAttribute,應該是
HtmlTextWriterAttribute
 枚舉的成員。該枚舉包含像
Align

Bgcolor

Class
 和
Onclick
 等項。您可以在 .NET Framework Class Library,HtmlTextWriterAttribute Enumeration 中找到完整的列表。value 輸入參數用於指定分配給特定 HTML 屬性的值。最後,如果您想添加一個
HtmlTextWriterAttribute
 枚舉中未定義的 HTML 屬性,可以使用
AddAttribute()
 方法的替代形式
AddAttribute(attributeName, value)
,其中的 attributeName 和 value 均為字串。

為了運用該資訊,我們建立一個作為確認按鈕的伺服器 Web 控制項。確認按鈕是一種提交按鈕,當使用者單擊此按鈕時,將顯示一個彈出式對話方塊,詢問使用者是否確定要繼續操作。使用者可以單擊“取消”,不提交表單。此項功能對用於刪除資訊的按鈕特別有用,因為終端使用者(或網站管理員)可能會在無意中單擊滑鼠刪除資料庫中的條目,如果沒有機會取消,將是非常令人煩惱的事。

為了減少工作量,我們從
System.Web.UI.WebControls.Button
 類中匯出 ConfirmButton Web 控制項,因為這個類本身已完成了涉及呈現提交按鈕的所有繁重工作。在匯出的類中,我們只需添加一個屬性,這樣使用者可以指定確認訊息,然後覆蓋按鈕的
AddAttributesToRender()
 方法,並添加一個屬性以處理用戶端事件
onclick

首先,在 Visual Studio .NET 中建立一個新的 Web Control Library(Web 控制項陳列庫)項目,或者在 ClientSideControls 項目中添加一個新的 Web Custom Control(Web 自訂控制項)。ConfirmButton 類的完整原始碼如下所示:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace ClientSideControls
{
   /// <summary>
   /// ConfirmButton 的摘要描述。
   /// </summary>
   [DefaultProperty("Text"),
      ToolboxData("<{0}:ConfirmButton runat=server></{0}:ConfirmButton>")]
   public class ConfirmButton : Button
   {
      [Bindable(true),
         Category("Appearance"),
         DefaultValue("")]
      public string PopupMessage
      {
         get
         {
            // 檢查 ViewState 中是否存在該項目
            object popupMessage = this.ViewState["PopupMessage"];
            if (popupMessage != null)
               return this.ViewState["PopupMessage"].ToString();
            else
               return "Are you sure you want to continue?";
         }

         set
         {
            // 指定 ViewState 變數
            ViewState["PopupMessage"] = value;
         }
      }

      protected override void AddAttributesToRender(HtmlTextWriter writer)
      {
         base.AddAttributesToRender(writer);

         string script = @"return confirm(""%%POPUP_MESSAGE%%"");";
         script = script.Replace("%%POPUP_MESSAGE%%",
            this.PopupMessage.Replace("\"", "\\\""));

         writer.AddAttribute(HtmlTextWriterAttribute.Onclick, script);
      }
   }
}

首先要注意的是,
ConfirmButton
 類是從
Button
 類匯出的。由於 Button 類已包含 Button Web 控制項使用的所有屬性和方法,因此我們所做的只是添加屬性和方法,以在使用者單擊按鈕時顯示一個確認對話方塊。現在我們需要一個屬性,即
PopupMessage
,它是要在確認彈出式對話方塊中顯示的訊息。預設情況下,這條訊息是“Are you sure you want to continue?”(您確定要繼續嗎?)如果使用 ConfirmButton 來確認刪除,可能需要將該訊息更改為“This action will permanently delete the selected item. Are you sure you want to do this?”(此操作將永久刪除所選項。您確定要繼續嗎?)

我們只需覆蓋一個方法,即
AddAttributesToRender()
。在此方法中,我們只要構建當觸發
<input>
 元素的
onclick
 事件時要執行的用戶端 JavaScript,然後通過傳入的
HtmlTextWriter
 對象的
AddAttribute()
 方法添加這段 JavaScript。關於這個方法,有一點要注意,必須將
PopupMessage
 屬性值中的所有雙引號執行個體替換為轉義雙引號(即
\"
)。另外還要注意,預設情況下,
AddAttribute()
 會對第二個參數中的字元進行 HTML 編碼。也就是說,ASP.NET Web 頁面中如果包含
PopupMessage
 屬性被設定為“Do you want to continue?”(要繼續嗎?)的 ConfirmButton,該頁面將發送以下 HTML 標籤:

<input type="submit" name="ConfirmButton1"
value="Click Me!" id="ConfirmButton1" onclick="return confirm
(&quot;Do you want to continue?&quot;);" />

如果您不熟悉 JavaScript 的
confirm(string)
 函數,那麼請您注意,該函數只接受一個字串參數,並顯示一個帶有特定字串的強制回應對話方塊。該對話方塊中包含兩個按鈕:“確定”和“取消”。如果單擊“確定”,
confirm()
 函數返回 True,否則返回 False。請注意,
onclick
 事件將返回
confirm()
 函數調用的結果。當通過單擊提交按鈕來提交表單時,如果提交按鈕的
onclick
 事件返回 False,則表單未被提交。因此,只有在使用者確認後,可以使用
confirm()
 函數提交表單。有關
confirm()
 的詳細資料,請參閱 ASP Warrior 網站中的 Javascript Confirm Form Submission。

 

圖 3:操作中的 ConfirmButton

ConfirmButton 在按鈕的
onclick
 事件處理常式中使用了內嵌的 JavaScript,還可以在 ConfirmButton 的
OnPreRender()
 方法的用戶端指令碼塊中建立一個函數,然後調整
onclick
 屬性以調用該函數。

小結
在本文中,我們探討了兩種通過 ASP.NET 伺服器控制項插入用戶端指令碼的方法。第一種方法是使用 Page 類的
RegisterStartupScript()
 和
RegisterClientScriptBlock()
 方法插入用戶端指令碼塊。第二種方法是向 HTML 元素的屬性添加用戶端指令碼。後者通過覆蓋 Web 伺服器控制項的
AddAttributesToRender()
 方法,並使用
HtmlTextWriter
 的
AddAttribute()
 方法來完成。

我們還在文中介紹了兩個簡單的伺服器控制項,它們都利用了用戶端指令碼來改進其功能。PopupGreeting 控制項在頁面首次載入時顯示一個模式彈出式對話方塊,ConfirmButton Web 控制項在使用者單擊按鈕提交表單時,提示使用者進行確認。

您可以在自己的伺服器控制項中插入用戶端指令碼,這將顯著改善使用者體驗。本文提供的兩個伺服器控制項相對比較簡單,在可用性和獨創性上沒有什麼突出之處。MetaBuilders.com 中展示了很多利用從 ASP.NET 伺服器控制項中插入用戶端指令碼而實現的功能,這些功能會給您留下深刻印象。在 MetaBuilders.com,您可以找到一些伺服器控制項,它們有的可以自動將焦點添加到文字框,有的可以在兩個下拉式清單之間傳遞條目,有的可以向下拉式清單中添加或刪除條目,還有的可以在一系列下拉式清單中顯示父子關係的資料,等等。最大的好處是,這些控制項是免費的,並包括完整的原始碼。

祝大家編程快樂!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.