2012年10月8日 星期一

Master Page

Advantages of using master pages include the following:

  • allow you to centralize the common functionality of your pages.
  • allow you to create one controls and code and apply the results to a set of pages.
  • allow you to control over the layout of the final pages
  • allow you to customize the master pages from individual content pages.

主版頁面

  • Master page is defined with the file extension .master
  • Master page inherits from the MasterPage Class。
  • Master page contain an @ Master directive 。
  • Master pages use ContentPlaceHolder controls to defines an area for content pages。

建立 MasterPage 和 ContentPage

下面是一個主版頁面與內容頁面的範例:

Master Page

繼承 MasterPage 類別。

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="Practice.Site1" %>

<head id="Head1" runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        
        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
public partial class Site1 : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
}

Content Page

使用 MasterPageFile 屬性,指定使用的主版頁面。

<%@ Page Language="C#" ...... MasterPageFile="Site1.Master" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>

有一點要注意:若在 Master Page 的 ContentPlaceHolder 中有置放任何控制項,只要 Content Page 有指定使用該區塊,那麼在 Master Page 的控制項都會清除。 除非 Content Page 完全沒有使用該 ContentPlaceHolder ,那麼在主版頁的控制項才會出現在 Content Page。

例如,在 MasterPage 中有個選單,若 ContentPage 要使用自已的選單,就可以加入一個 <Content></Content> ,它自然就會覆蓋主版頁的選單。 若不加入 Content 控制項,就會延用主版頁的選單。

MasterPage 等級:

  1. 頁面等級(page level):在每個頁面繫結主版頁面。
    <%@ Page Language="C#" MasterPageFile="MySite.Master" %>
    
  2. 應用程式等級(application level):設定 web.config 。
    <pages masterPageFile="MySite.Master" />
    
  3. 目錄等級(folder level):設定目錄中的 web.config 。

MasterPage 事件的順序:

Page_PreInit
<span style="color:Blue">UserControl.Page_Init</span><br/> <span style="color:Orange">MasterPage.Page_Init</span><br/> Page_Init<br/> Page_InitComplete<br/> Page_Load<br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Orange">MasterPage.Page_Load</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Blue">UserControl.Page_Load</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Green">Button1_Click</span><br/> Page_LoadComplete<br/> Page_PreRender<br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Orange">MasterPage.Page_PreRender</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Green">TextBox1_PreRender</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Green">Button1_PreRender</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Blue">UserControl.Page_PreRender</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Blue">UserControl.TextBox1_PreRender</span><br/> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:Blue">UserControl.Button1_PreRender</span><br/> Page_PreRenderComplete<br/> </div> <p> 1.在 Load 事件之前,MasterPage 的事件會先觸發,之後則由 ContentPage 的事件先觸發。 2.在 MasterPage 中,最早的事件是 OnInit 。 </p> </div> </div> <h1 class="collapsable" onclick="displayDiv('MasterPage 與 ContentPage 的互動')">MasterPage 與 ContentPage 的互動</h1> <div id="MasterPage 與 ContentPage 的互動"> <h2 class="collapsable" onclick="displayDiv('讀取 MasterPage 中的屬性與方法')">由 ContentPage 讀取 MasterPage 中的屬性與方法</h2> <div id="讀取 MasterPage 中的屬性與方法"> <p>The basic process to reference master page properties from a content page is as follows:</p> <ol> <li> 在 <a target="_blank" href="http://msdn.microsoft.com/zh-tw/library/system.web.ui.masterpage.aspx">MasterPage</a> 中建立公開屬性.<br /> <div class="source_code"><pre class="brush:c#;" title="Master Page"> public string CompanyName { get { return (string)ViewState["CompanyName"]; } set { ViewState["CompanyName"] = value; } } protected void Page_Load(object sender, EventArgs e) { CompanyName = "vito corp."; }
  • 在 ContentPage 中設定「@ MasterType」宣告,用以建立對主版類別的參考。
    <%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" ...%>
    
    <%@ MasterType VirtualPath="~/Site1.master" %>
    
  • 由 ContentPage 中,使用 Master 類別,讀取 MasterPage 中的 Properties, Methods。
    protected void Page_PreRender(object sender, EventArgs e)
    {
        //access Master's Property
        Page.Header.Title = Master.CompanyName;
    
        //invoke Master's Method
        Page.Header.Title = Master.GetCompanyName();
    }
    
  • 由 ContentPage 讀取 MasterPage 的 Controls

    在內容頁,除了可以讀取主版頁的屬性之外,也可以呼叫 Master.FindControl 方法,利用控制項的名稱找出控制項。

    protected void Page_PreRender(object sender, EventArgs e)
    {
        //reference Control
        Label Label1 = (Label)Master.FindControl("Label1");
        Page.Header.Title = Label1.Text;
    }
    

    由 MasterPage 讀取 ContentPage 的 Controls

    叫用 ContentPlaceHolder.FindControl 以取得內容頁的控制項。

    Button button1 = ContentPlaceHolder1.FindControl("btnTest") as Button;
        if (button1 != null)
        {
            myMessage.Show(button1.Text + " button exist");
        }
    

    由 MasterPage 叫用 ContentPage 的 Method

    透過 ContentPlaceHolder 可以取得 ContentPage 中的 Page 型別,就可以叫用它的方法

    ContentPage_with_MasterPage contentpage1 = ContentPlaceHolder1.Page as ContentPage_with_MasterPage;
        contentpage1.hello();
    

    不過,以上做法並不好,這將使得主版頁與內容頁綁的太緊。若要執行內容中的方法,也可以引發事件,由內容頁自行訂閱處理,會是比較好的做法。

    public event EventHandler TestButtonClick;
    
        protected void RaiseEvent_Click(object sender, EventArgs e)
        {
            if (TestButtonClick != null)
                TestButtonClick(sender, e);
        }
    
    protected void Page_PreInit(object sender, EventArgs e) {
            // Create an event handler for the master page's TestButtonClick event  
            Master.TestButtonClick += new EventHandler(TestButtonClick); 
        }
    
        private void TestButtonClick(object sender, EventArgs e)
        {
            myMessage.Show("TestButtonClick inf Content Page");
        }
    

    如果想由 MasterPage 傳遞參數給 ContentPage ,也可以用這個方法。

    動態改變 MasterPage

    要改變 ContentPage 的主版頁,必須在 Page_PreInit 事件之前,變更 Page.MasterPageFile 屬性。

    protected void Page_PreInit(object sender, EventArgs e)
    {
        if (Session["MasterPageFile"]!=null)
            MasterPageFile = (string)Session["MasterPageFile"];
    }
            
    protected void btnMaster1_Click(object sender, EventArgs e)
    {
        Session["MasterPageFile"] = @"~/C09_Customizing_and_Personalizing/Site1.Master";
        Response.Redirect(Request.Path);
    }
    
    protected void btnMaster2_Click(object sender, EventArgs e)
    {
        Session["MasterPageFile"] = @"~/C09_Customizing_and_Personalizing/Site2.Master";
        Response.Redirect(Request.Path);
    }
    

    巢狀 MasterPage

    MasterPage 支援巢狀 MasterPage ,用法也沒什麼特別,但有幾點需注意:

    若要找主版頁面上的控制項,就要看在那一層的主版頁面,然後用如下的語法

    Master.Master.FindControl("ControlID");
    

    若要動態變更巢狀 MasterPage 的 MasterPage ,前面有提過,必須在 Page_PreInit 事件變更,但是,因為 MasterPage 本身沒有這個事件, 所以,必須一律在 ContentPage 中,判斷 MasterPage 是否還有 MasterPage,然後用如下的語法變更。

    Master.Master.MasterPageFile = "../Master2.master";
    

    沒有留言:

    張貼留言