網頁經常需要在前端以 JavaScript 對話窗顯示訊息,如果每一個網頁都要寫一次,覺得有點麻煩。既然每個網頁都有套用 master page,乾脆把這個顯示對話窗的機制寫在 master page 裡面,讓所有網頁共用。

可是 master page 怎麼知道目前的 content page 有沒有訊息要顯示?要顯示的內容是什麼?

一個簡單的方法是,我們可以在 master page 裡面放一個隱藏欄位 (hidden field),並且在 master page 的前端 onload 事件裡面把這個隱藏欄位的內容以 alert() 函式秀出來。這樣一來,只要 content page 有需要顯示訊息,就先在 server 端把訊息字串指定給這個隱藏欄位的值。等到網頁在前端載入完成,就會自動秀出這個訊息視窗。

以下是簡易的練習步驟 (假設 master page 的檔名是 MyMasterPage.master):

1.在 MyMasterPage.master 網頁上加入一個隱藏欄位: HiddenField1。

2.編輯 MyMasterPage.master 原始程式碼,指定 <body> 的 onload 屬性為某個 JavaScript 函式,例如:

<body onload="OnLoad()" ....>

然後撰寫對應的 OnLoad() 函式:

<body ....>
    ....
    <script language="javascript" type="text/javascript">
      function OnLoad()
      {
        ShowAlertMessage(); // 顯示對話訊息 (此函式由程式動態注入)
      }
    </script>
</body>

這樣網頁在前端載入時就會呼叫 OnLoad(),而 OnLoad 裡面又會呼叫 ShowAlertMessage() 以顯示訊息窗。這個顯示訊息的函式不能寫死,必須動態產生。因此這裡我們還會用到注入 JavaScript 的技巧(及下個步驟)。

3.編輯 MyMasterPage.master.cs,在 Page_Load 事件撰寫注入 JavaScript 的程式碼:

    protected void Page_Load(object sender, EventArgs e)
    {
        // 每次網頁載入後都要把值清空, 以免因狀態自動保留的緣故,重複顯示上一次的訊息
         HiddenField1.Value = "";
        if (!Page.ClientScript.IsClientScriptBlockRegistered("ShowAlertMessage"))
        {
            // 注入 client script
            StringBuilder sb = new StringBuilder();
            sb.Append("function ShowAlertMessage()\n");
            sb.Append("{\n");
            sb.Append("  var obj = document.getElementById(\"" + HiddenField1.ClientID + "\"); \n");
            sb.Append("  if (obj != null && obj.value != \"\") {\n");
            sb.Append("    alert(obj.value); \n");
            sb.Append("  }\n");
            sb.Append("}\n");

            Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ShowAlertMessage", sb.ToString(), true);
        }
    }

這樣在執行時會產生類似下面的 JavaScript:

<script type="text/javascript">
  <!--
  function ShowAlertMessage()
  {
    var obj = document.getElementById("ctl00_HiddenField1");
    if (obj != null && obj.value != "")
    {
      alert(obj.value); 
    }
}
// -->
</script>

4.在 content page 裡面如果有訊息要顯示,只要指定 master page 的 HiddenField1.Value 屬性即可。但是 HiddenField1 的存取層級是 protected,在 content page 裡面無法存取到,因此要用上一篇的技巧,在 master page 裡面定義一個新的公開屬性,把 HiddenField1 的 Value 屬性透過該屬性公佈給外界存取。假設此屬性名稱為 AlertMessage,在 MyMasterPage.master.cs 中的定義會像這樣:

    public string AlertMessage
    {
        get
        {
            return HiddenField1.Value;
        }
        set
        {
            HiddenField1.Value = value;
        }
    }

5.透過 MyMasterPage.master 裡面的 @MasterType 指示詞來指定 content page 的 Master 屬性的型別(參考上一篇)。這樣在 content page 的 code behind 程式碼裡面,就可以直接以下列程式碼指定 master page 的 AlertMessage 屬性:

  this.Master.AlertMessage = "Hello!";

這行程式碼會設定 master pager 的 AlertMessage 屬性值,也就是 HiddenField1 的 Value 屬性。然後整個網頁在前端載入時,前端網頁會觸發 onload 事件,然後呼叫動態注入的 JavaScript 函式: ShowAlertMessage(),在此函式中會檢查隱藏欄位值,如果不是空字串,就利用 alert() 把訊息顯示出來。

That's all! Happy coding :)