随笔 - 5  文章 - 1 评论 - 22 trackbacks - 0

 

从界面的角度来看,母版的使用是很简单的,如果联系Page类、HttpHandle等技术点来看,应该思考一下应用了母版的aspx页面是如何进行HttpHandle处理的。

<httpHandles>配置中,Page类是.aspx文件的处理类,这就意味着应用了母版的aspx页面同样也是Page类处理的。那么就要思考母版页上的控件是如何与aspx上的控件进行结合的。

先来分析一下应用了母版页的aspx的响应流程:

①用户的Web请求,触发对应于.aspxHttpHandle(即:Page类)开始工作。

Page类首先读取@ Page指令。如果该指令引用一个母版页,则也读取该母版页。如果这是第一次请求这两个页,则两个页都要进行编译。

③包含更新的内容的母版页合并到aspx页的的控件树中。

aspx页面中各个 Content 控件的内容合并到母版页中相应的ContentPlaceHolder控件中。

⑤浏览器中呈现得到的合并页。

最后会形成这么一个层次关系的控件树:

 

如果是嵌套母版,则在ContentPlaceHolder下又有一颗Mater Page子树。

一般说来,此结构对如何构造页或编写页的程序无任何影响。但是在某些情况下,如果在母版页上设置一个页范围的属性,则该属性可能会影响aspx页中控件的行为,这是因为母版页是页上控件的最近的父级。例如,如果在aspx页上将 EnableViewState属性设置为true,而在母版页中将相同的属性设置为false,实际上会禁用视图状态,因为母版页上的设置具有优先权。

由于母版页最终会解析成为aspxPage控件容器的下一级控件容器,因此在母版页上的路径在运行时,都会以aspx页为准,如:如果获取HttpRequest对象的CurrentExecutionFilePath属性,则无论是在aspx页代码还是母版页代码中,路径都表示aspx页的位置。

对于服务器控件中的URL相关属性,ASP.net会自动的修改为相对于aspx页面的路径。

既然母版页是Page控件容器的下一级控件容器,因此在页面事件触发顺序上,母版页也就象是Page上的一个控件,其事件触发顺序如下:

母版页控件 Init 事件à内容控件 Init 事件à母版页 Init 事件à内容页 Init 事件à内容页 Load 事件à母版页 Load 事件à内容控件 Load 事件à内容页 PreRender 事件à母版页 PreRender 事件à母版页控件 PreRender 事件à内容控件 PreRender 事件。

与控件在页面的触发顺序比较一下,从事件的触发顺序上看,母版页就完全如何Page中的控件一样。

aspx页上可以引用母版上定义的控件、方法和属性。

实现此功能,需要分为两步:

第一步:在aspx页中添加<@ MasterType>指令,将Page类中的Master属性强类型化。

第二步:通过FindContorl方法,在Master的控件树上找到所需要的控件。

建立MasterPage.masterIndex.aspx,在母版和Index.aspx中分别插入一个文本框和一个按钮,然后在Index.aspx中引用MasterPage中的按钮和文本框控件以及MasterPage.master.cs中定义的属性和方法。

例中除了引用母版控件外,还需要引用母版类中定义的属性和方法,注意:只有public的属性和方法才可能被aspx页面引用。

第一步:打开MasterPage.master.cs文件,添加如下程序。

public partial class MasterPage : System.Web.UI.MasterPage

{

    protected void Page_Load(object sender, EventArgs e)

    {

    }

    protected void Button1_Click(object sender, EventArgs e)

    {

        this.TextBox1.Text = "这是母版中的按钮";

    }

 

    private string pageName=string.Empty;

    public string PageName

    {

        get { return this.pageName; }

        set { this.pageName = value; }

    }

 

    public void SetName(string name)

    {

        this.pageName = name;

    }

}

 

第二步:打开Index.aspx,在@ Page指令下面增加@ Master指令。

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

或:

<%@ MasterType TypeName="MasterPage"%>

@ Master指令设置后,可以发现Page类中的Master属性已被转化为了MasterPage类型了。

第三步:打开Index.aspx.cs,在Page_Load中写入:

protected void Page_Load(object sender, EventArgs e)

{

        TextBox tb = (TextBox)Master.FindControl("TextBox1");

        tb.Text = "Aspx页引用";

 

        //引用母版类中定义的Public属性和方法

        Master.PageName = "abc";

        Master.SetName("ABC");

}

如果TextBox控件不是直接放在页面上,而是放置在其它控件容器中,则要先引用该容器,再在该容器下FindControl。在这个思路下,可以来验证一下上中控件树的正确性。

Index.aspx.cs中,通过母版上FindControl的方式来找到定义在Index.aspx页面上的Button按钮(IDButton1)。当然这段程序是很无聊的,没有实用价值,只能用来验证控件树,因为在Index.aspx.cs中通过this.Button1便可以获取对这个Button的引用了。

ContentPlaceHolder cp = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");

Button btn = (Button)cp.FindControl("Button1");

btn.Text = "aspx修改";

这段代码说明了Index.aspx中定义在ContentPlaceHolder1区域中的控件,也就是是母版中ContentPlaceHolder1容器中的控件,证明了中控件树的正确性。
posted on 2008-06-06 08:27 李彦 阅读(577) 评论(2) 编辑 收藏