MasterPage的另外一种实现方式


我们知道WEB页面最终呈现给用户的是HTML,如下所示的一种格式:<Html><body><form><table><tr><td>(.....每个页面公共部分)....<table><tr></td>(..每个页面私有部分)</td></tr></table></td></tr></table></body></Html>
为此我们可以建立一个模板页面,在<%和%>中的内容我们规定是每个页面的私有部分,这里的<%没有特别意义,只不过一个标志而已,如下我们可以建立一个MasterPage.htm
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
<html>
<head>
<title>模版页面</title>
</head>
<body>
<linkhref="../CSS/trafficprice.css"type="text/css"rel="stylesheet">
<tablecellSpacing="0"cellPadding="0"width="100%"border="0"ID="Table1">
<trbgColor="#336699">
<tdcolSpan="2"height="60">
<h1class="style1">公司标头</h1>
</td>
</tr>
<tr>
<tdcolSpan="2"><%#TopMenu%></td>
</tr>
<tr>
<tdcolSpan="2"><%#UserStatus%></td><!--~/UserControl/WebUserHelp.ascx-->
</tr>
<trvAlign="top">
<tdbgColor="#dbeaf5"><%~/UserControl/menu.ascx%></td>
<tdwidth="100%"><%CONTENT%></td>
</tr>
<trbgColor="#336699">
<tdcolSpan="2"height="30"><spanclass="style1">联系人、版权信息</span></td>
</tr></table>
</body>
</html>
〈%CONTENT%〉是表示其中的内容将被应用模板的页面内容所取代。对于ASP。NET的页面生成情况,我们可以把所有的元素归结为三种控件LiteralControl,编译是就能确认的用户控件(叫做WebCtrl)在模本中以<%~/UserControl/menu.ascx%> ~/UserControl/menu.ascx表示用户控件的路径,还有一种情况就是编译是系统不知道具体的用户控件在运行时才知道的(比如用户没有权限执行用户控件的功能,那就没有必要加载该用户控件),我们暂且就他为延迟用户控件DelayDefCtrl,在模板中用〈%TopMenu%〉表示。针对上面三种情况,我们定义三种控件类(LiteralItem、WebCtrlItem、DelayDefItem),和一个基类(MasterPageItem)
usingSystem;
usingSystem.Web.UI;

namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///MasterPageItem的摘要说明。
///</summary>

internalabstractclassMasterPageItem{
publicabstractControlCreateControl(BasePageparaPage);
}

}
<%#TopMenu%><%#TopMenu%><%~/UserControl/menu.ascx%><%~/UserControl/menu.ascx%><%~/UserControl/menu.ascx%>
usingSystem;
usingSystem.Web.UI;

namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///LiteralItem的摘要说明。
///</summary>

internalclassLiteralItem:MasterPageItem{
privatestringmemLiteral;
publicLiteralItem(stringparaLiteral){
memLiteral
=paraLiteral;
}


publicoverrideControlCreateControl(BasePageparaPage){
returnnewLiteralControl(memLiteral);
}

}

}

usingSystem;
usingSystem.Web.UI;

namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///WebCtrlItem的摘要说明。
///</summary>

internalclassWebCtrlItem:MasterPageItem{
stringmemCtrlUri;
publicWebCtrlItem(stringparaCtrlUri){
memCtrlUri
=paraCtrlUri;
}

publicoverrideControlCreateControl(BasePageparaPage){
returnparaPage.LoadControl(memCtrlUri);
}

}

}

usingSystem;
usingSystem.Web.UI;

namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///DelayDefItem的摘要说明。
///</summary>

internalclassDelayDefItem:MasterPageItem{
privatestringmemIndex;

publicDelayDefItem(stringparaIdx){
memIndex
=paraIdx;
}

publicoverrideControlCreateControl(BasePageparaPage){
stringtempCtrlUri=paraPage.MasterCtrlNameDir[memIndex]asstring;
if((tempCtrlUri!=null)&&(tempCtrlUri.Length>1))
returnparaPage.LoadControl(tempCtrlUri);
returnnull;

}

}

}

接下来我们就可以分析模板页面并生成上面所说的三种控件,下面是具体的实现类(MasterPageTemplate.cs)
usingSystem;
usingSystem.IO;
usingSystem.Text;
usingSystem.Web;
usingSystem.Collections;
usingSystem.Collections.Specialized;
namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///MasterPageTemplate的摘要说明。
///</summary>

internalclassMasterPageTemplate{
privateconststringBodyStartTag="<body>";
privateconststringBodyEndTag="</body>";
privateconststringCtrlStartTag="<%";
privateconststringCtrlEndTag="%>";
privateconststringContentTag="CONTENT";

staticprivatereadonlyEncodingmemEncoding;

privateIListtempletctl=null;

staticMasterPageTemplate(){
memEncoding
=Encoding.GetEncoding(936);
}


publicMasterPageTemplate(stringparaUri){//模板页的路径
stringtempMasterPageTemplateFilename
=HttpContext.Current.Server.MapPath(paraUri);
stringtempMasterPageTemplate;
using(StreamReadertempReader=newStreamReader(
tempMasterPageTemplateFilename,
memEncoding,
true)){
tempMasterPageTemplate
=tempReader.ReadToEnd();
}

inttempStart=tempMasterPageTemplate.IndexOf(BodyStartTag);
if(tempStart<0)
return;
tempStart
+=BodyStartTag.Length;
templetctl
=newArrayList();
LoadItems(templetctl,tempMasterPageTemplate,tempStart);
}


///<summary>
///
///</summary>
///<paramname="paraList"></param>
///<paramname="paraTemplate"></param>
///<paramname="paraStart"></param>
///<returns>trueifstillhavedatatoread</returns>

staticprivatevoidLoadItems(
IListctllist,
stringparaTemplate,intparaStart){
inttempTest,tempLen;
inttempStart=paraStart;
ArrayListparaList
=newArrayList();

while(true){
tempTest
=paraTemplate.IndexOf(CtrlStartTag,tempStart);
if(tempTest<0){
tempTest
=paraTemplate.IndexOf(BodyEndTag);
if(tempTest<0)
thrownewApplicationException(
"masterpageisinvalid:nobodyendtag");
tempLen
=tempTest-tempStart;
if(tempLen>0){
paraList.Add(
newLiteralItem(
paraTemplate.Substring(tempStart,tempLen
)));
}

ctllist.Add(paraList);
return;//endofbody
}

tempLen
=tempTest-tempStart;
if(tempLen>0){
paraList.Add(
newLiteralItem(
paraTemplate.Substring(tempStart,tempLen
)));
}

tempStart
=tempTest+CtrlStartTag.Length;
tempTest
=paraTemplate.IndexOf(CtrlEndTag,tempStart);
if(tempTest<0)
thrownewApplicationException("Unclosetag");
tempLen
=tempTest-tempStart;
if(tempLen==0)
thrownewApplicationException("Emptycontroltag");
stringtempUri=paraTemplate.Substring(tempStart,tempLen).Trim();
if(tempUri.Length==0)
thrownewApplicationException("controlisblank");
tempStart
=tempTest+CtrlEndTag.Length;
if(tempUri==ContentTag){
paraTemplate
=paraTemplate.Substring(tempStart);
paraList.Reverse();
ctllist.Add(paraList);
LoadItems(ctllist,paraTemplate,
0);
return;
}

if(tempUri[0]=='#')
paraList.Add(
newDelayDefItem(tempUri));
else
paraList.Add(
newWebCtrlItem(tempUri));
}

}


publicIListTemCtl{
get{
returntempletctl;
}

}

}

}

最后我们实现一个BasePage,它是一个继承自Page的一个类,我们让所有应用MasterPage的页面都继承这个类,通过重写CreateChildControls()方法,加载我们生成的三种控件。
usingSystem;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.HtmlControls;
usingSystem.Security.Principal;
usingSystem.Collections;
usingSystem.Collections.Specialized;
//
usingTrafficPrice.CommunalAccess.DataDefine;

namespaceTrafficPrice.CommunalAccess.TempletPage
{
///<summary>
///BasePage的摘要说明。
///</summary>

publicclassBasePage:Page
{
staticprivatereadonlyIDictionarymemMasterPages
=newHybridDictionary();

privatestringmemMasterPageUri=null;
privateMasterPageTemplatememTemplate=null;
privateIDictionarymemMasterCtrlNameDir=newHybridDictionary();
//
privateProfileInformationprofile=null;

publicBasePage(){
}


publicBasePage(stringparaBasePageUri){
memMasterPageUri
=paraBasePageUri;
}

protectedstringPageUrl{
set{
memMasterPageUri
=value;
}

}





publicIDictionaryMasterCtrlNameDir{
get{
returnmemMasterCtrlNameDir;
}

}



overrideprotectedvoidOnInit(EventArgse){
base.OnInit(e);
}


privateControlGetControl(Typetype,boolprefix){
ControltempPlaceHolder
=this.FindControl(prefix?"memMasterPagePrefix":"memMasterPageSuffix");
if(tempPlaceHolder==null)
returnnull;
ControlCollectioncontainer
=tempPlaceHolder.Controls;
foreach(Controlcontrolincontainer){
if(type.IsAssignableFrom(control.GetType()))
returncontrol;
}

returnnull;
}

protectedControlGetControl(Typetype,stringfatherCtl){
ControltempPlaceHolder
=this.FindControl(fatherCtl);
if(tempPlaceHolder==null)
returnnull;
ControlCollectioncontainer
=tempPlaceHolder.Controls;
foreach(Controlcontrolincontainer){
if(type.IsAssignableFrom(control.GetType()))
returncontrol;
}

returnnull;
}


privatevoidAddControls(
ControlCollectionparaHost,IListparaList,
boolparaAtHead){
if(paraList==null)
return;
foreach(MasterPageItemtempIteminparaList){
ControltempCtrl
=tempItem.CreateControl(this);
if(tempCtrl!=null){
if(paraAtHead)
paraHost.AddAt(
0,tempCtrl);
else
paraHost.Add(tempCtrl);
}

}

}


protectedoverridevoidCreateChildControls(){
if((memTemplate==null)
&&(memMasterPageUri!=null)&&(memMasterPageUri.Length>0)){
memTemplate
=memMasterPages[memMasterPageUri.ToLower()]asMasterPageTemplate;
if(memTemplate==null){
memTemplate
=newMasterPageTemplate(memMasterPageUri);
if(memTemplate!=null)
memMasterPages[memMasterPageUri]
=memTemplate;
}

}


base.CreateChildControls();

if(memTemplate!=null){
ControltempForm
=null;
foreach(ControltempCtrlinControls){
if(tempCtrlisHtmlForm){
tempForm
=tempCtrl;
break;
}

}

if(tempForm!=null){
ControlCollectiontempHost
=tempForm.Controls;
IListPlaceHolderCtl
=newArrayList();
foreach(ControltempControlintempHost){
if(tempControl.GetType().IsAssignableFrom(typeof(System.Web.UI.WebControls.PlaceHolder))){
PlaceHolderCtl.Add(tempControl);
}

}

for(inti=0;i<PlaceHolderCtl.Count;i++){
if(i==PlaceHolderCtl.Count-1){
AddControls(((Control)PlaceHolderCtl[i]).Controls,(IList)memTemplate.TemCtl[i],
false);
return;
}

AddControls(((Control)PlaceHolderCtl[i]).Controls,(IList)memTemplate.TemCtl[i],
true);
}

}

}

}

}

}

下面是应用摸板的例子:
<%@RegisterTagPrefix="uc1"TagName="pagenavigation"Src="../UserControl/pagenavigation.ascx"%>
<%@Pagelanguage="c#"Codebehind="BrowBulkGoods.aspx.cs"AutoEventWireup="false"Inherits="TrafficPrice.SeaTransport.BrowBulkGoods"%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
<HTML>
<HEAD>
<title>浏览散货信息</title>
<metacontent="MicrosoftVisualStudio.NET7.1"name="GENERATOR">
<metacontent="C#"name="CODE_LANGUAGE">
<metacontent="JavaScript"name="vs_defaultClientScript">
<metacontent="http://schemas.microsoft.com/intellisense/ie5"name="vs_targetSchema">
</HEAD>
<bodyMS_POSITIONING="GridLayout">
<formid="Form1"method="post"runat="server">
<asp:placeholderid="memMasterPagePrefix"runat="server"></asp:placeholder>
<tablecellSpacing="0"cellPadding="0"width="95%"border="0">
<tr>
<tdvAlign="top">
<tablecellSpacing="0"cellPadding="0"width="100%"border="0">
<tr>
<td>thisisatestforapplyMasterPage
</td>
</tr>
</table>
</td>
</tr>
</table>
<asp:placeholderid="memMasterPageSuffix"runat="server"></asp:placeholder></form>
</body>
</HTML>
注意被在两个<asp:placeholder id="memMasterPagePrefix" runat="server">包围的内容将取代摸板页中〈%CONTENT%〉中的内容。如果有多个〈%CONTENT%〉那么也应该有多个<asp:placeholder 来分割。当然该类继承自BasePage,基类的构造函数的参数为摸板页面的路径。
优质内容筛选与推荐>>
1、Spinner默认选择问题
2、蒙皮权重
3、后缀自动机三·重复旋律6
4、contest(2)
5、xib自定义View


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号