2011/4/29

[ASP.NET] 擷取 Master Page 觸發的事件

很多事情都是必須遇到了才會重視。使用 Master Page 是每個 ASP.NET 程式設計師都必須了解、甚至精通的; 我也一直覺得我對這部份的技術非常精通, 直到我在最近設計的網站遇到某個比較少用到的功能, 才發現有很多事情並沒有原先想像的那麼直覺。什麼事情呢? 就是我原本放置在 Master Page 部份的控制項, 如果我必須在 Content Page 處理它的事件, 應該怎麼做?

一開始, 我覺得這不應該是個問題, 但是真正下手之後, 才發現解法並沒有那麼直覺。經過明查暗訪, 終於找到了解決的方法, 如果你剛好也遇到這個問題, 不妨參考一下我的解法。

其實解法講穿了就沒什麼學問了! 因為它根本就和我在「[入門文章] ASP.NET 事件與委派詳論」一文所描述的做法幾乎是一模一樣的, 但是在這個問題中另外有個關鍵點, 請稍為留意。

首先, 建立一個名為 mp.master 的 Master Page 檔案, 並在裡面放置一個按鈕物件 (Button1), 設定它的 Click 事件處理函式 (Button1_Click). 然後再建立一個 Web Form (例如稱為 Default2.aspx), 並指定它的 Master Page 檔案為 mp.master。

在 mp.master.cs 中加入以下程式碼:

public delegate void MasterPageEventHandler(object sender, System.EventArgs e);

public partial class mp : System.Web.UI.MasterPage
{
    public event MasterPageEventHandler MasterButton;

    protected void Page_Load(object sender, EventArgs e)
    { }

    protected void Button1_Click(object sender, EventArgs e)
    {
        if (MasterButton != null)
            MasterButton(sender, e);
    }
}

如以上程式, 我在 mp.master.cs 中宣告了一個名為 MasterPageEventHandler, 存取層級為 public 的 Delegate。接著, 在類別中宣告名為 MasterPageEventHandler 的公開事件, 這是為了給 Content Page 觸發所用的。如果你看不懂以上這一段話, 你真的必須先去看看「[入門文章] ASP.NET 事件與委派詳論」這篇入門文章。

現在, 請在 Default2.aspx.cs 中寫入以下程式:

    protected void Page_Load(object sender, EventArgs e)
    {
        Master.MasterButton += new MasterPageEventHandler(ButtonHandler);
    }

    void ButtonHandler(object sender, EventArgs e)
    {
        // Do whatever you want
        Label1.Text = "Button \"{0}\" is pressed", ((Button)sender).ID);
        Button btn = (Button)sender;
        btn.Text = "Button Captured!";
    }

在以上程式中, 我們可以在 Page_Load 事件處理函式中附加 mp.master 的 MasterButton 這個公開事件的事件處理函式 ButtonHandler(), 至於你要在這個事件處理函式要做什麼事情, 那就由你自己決定了。

但是, 請特別注意, 如果你現在急忙忙的程式拿去執行, 一定會發生編譯上的錯誤, 也絕對無法執行! 這個解決有一個關鍵點, 那就是你必須在 Content Page 中加入至關緊要的一段指示, 那就是在 Default2.aspx 頂站的 @Page 指示詞下面, 再加上一段 @MasterType指示詞 (我就是忘記加上這一段):

<%@ MasterType VirtualPath="~/mp.master"%>

如此, 你就可以在 Content Page 中攔截到 Master Page 上的控制項所觸發的事件了。當然, 我在這個範例中使用的是 Button 控制項, 如果你將使用的控制項並不是 Button, 而是 TextBox, RadioButtonList 等等, 程式中對應的部份必須跟著稍做修改, 請自己舉一反三, 我就不另說明了。

1 則留言:

  1. 不知您是否有試過Materpage的TreeView
    在子頁面點擊事件是否有反應!!
    因為我嘗試用了您提供的方法,按鈕 確實可以,
    但是我不曉得為何TreeView一直沒反應!!
    不知道是否能幫我???

    回覆刪除