|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
我之所以想学。NET,是因为一直觉的BILLGATES好厉害,希望有一天能去微软,虽然现在还距离遥远,呵呵:)asp.net|服务器|控件<P> 在后面的文章中,次要先容了服务器控件的基础观点、基础实际,这些内容是构建一切自界说服务器控件的基石。但是,仅仅依托这些常识还不敷以创立出优异的服务器控件。由于,分歧范例的服务器控件具有分歧的创立办法,开辟职员必需在把握基础观点和实际以后,把握分歧范例服务器控件的开辟办法。本文及其随后几篇文章将具体先容与创立复合控件相干的内容。本文重点先容有关复合控件的观点、创立办法等实际,然后,经由过程一个典范示例加深读者关于复合控件创立办法的了解。
复合控件概述
复合控件中的“复合”一词标明该范例控件实质上由多个组件组合而成。同时,复合控件对外表露的成员工具一般由组成组件的办法和属性供应,而且大概到场一些新的成员。复合控件也能够完成自界说事务,并处置并激发子控件所引发的事务。就功效方面而言,复合控件的功效要比复杂组合几个控件的功效要壮大的多,并且良多时分具有必定的专项性。比方,ASP.NET2.0新增的Login控件就是一个典范的复合控件。该控件用户界面由多个独自控件组合而成,而且利用单一的API对控件举行设置和会见。别的,Login控件因为与成员资历等功效集成的缘故原由,因而,其具有疾速完成用户登录的功效。
大概部分有履历的读者在懂得了复合控件的基础观点以后会有所困惑:复合控件与用户控件仿佛十分类似,那末它们之间有甚么区分吗?究竟甚么时分创立复合控件,甚么时分创立用户控件呢?回覆这个成绩,我们必需从用户控件的基础观点动手举行研讨。
复杂而言,用户控件是指在一个项目中,因为一样一些功效模块在多处援用,比方,导航菜单等,能够把这一块代码做成一个用户控件,然后,在必要援用的页面中注册后,间接按控件利用的体例援用,省往了反复编写不异代码的事情。就复合控件与用户控件的区分而言,次要能够总结为以下几点:
1、复合控件创作的最短计划时撑持,用户控件创作的完整计划时撑持。在可视化计划器中,创感化户控件与创作ASP.NET页没有不同。
2、复合控件是以方针为大众言语运转库的面向工具的编程言语,如C#,是用编程体例创作的用户控件是利用ASP.NET页语法和剧本块声明性地创作的。
3、复合控件是作为程序集(.dll)编译和坚持的。用户控件是带有.ascx扩大名的文本文件。
4、复合控件十分适于创作一样平常的可从头公布的控件,用户控件合适使用程序特定的功效。
5、可将复合控件增加到可视化计划器的工具箱中并拖放到页面上,利用时能够在属性框中计划,用户控件只能在HTML中编写。
经由过程以上内容,信任读者已可以基础懂得了复合控件。上面先容一下创立复合控件的完成办法。在这个过程当中,开辟职员必需掌控以下几个要点:
第1、一般情形,复合控件类必需派生自System.Web.UI.WebControls.CompositeControl类。这一点与ASP.NET1.x情况下开辟复合控件有些分歧。在ASP.NET1.x中,复合控件必需完成System.Web.UI.INamingContainer接口。但是,在ASP.NET2.0下,复合控件类的基类则产生了变更。上面复杂先容一下CompositeControl类。
CompositeControl类是一个笼统类,该类可为自界说控件供应定名容器和控件计划器功效,而且可包括全体子控件或利用其他控件功效。CompositeControl类的声明朝码以下所示:
publicabstractclassCompositeControl:WebControl,INamingContainer,ICompositeControlDesignerAccessor
如上代码所示,CompositeControl类下层自WebControl基类,而且完成INamingContainer和ICompositeControlDesignerAccessor接口。INamingContainer是一个没无方法的标志接口。当控件在完成INamingContainer时,页框架可在该控件下创立新的定名局限,因而,可以确保子控件在控件的分层树中具有独一的称号。当复合控件公然模板属性,供应数据绑定或必要传送事务到子控件时,这长短常主要的。ICompositeControlDesignerAccessor接口使复合控件计划器能够在计划时从头创立其联系关系控件的子控件。该接口包括一个必要完成的办法RecreateChildControls。该办法使复合控件的计划器能够在计划时从头创立该控件的子控件。
别的,假如创立的是数据绑定复合控件,那末自界说控件类的基类应当是CompositeDataBoundControl。有关该类的详细内容,请读者查阅相干材料。
第2、必需重写Control基类的CreateChildControls办法,以便对子控件举行初始化、实例化,并将其增加到控件树中。CreateChildControls用于关照利用基于分解完成的服务器控件,创立它们包括的任何子控件,以便为回发或出现做筹办。重写该办法是完成复合控件的关头地点。这类类撰写的办法将关照.NET框架有关复合控件中包括哪些子控件,和各个子控件在控件树中的地位和干系等外容。经由过程这类办法,复合控件将复用子控件供应的完成来举行出现、事务处置、款式及其他功效。
在完成复合控件过程当中,除把握CompositeControl基类和CreateChildControls办法以外,ASP.NET2.0还供应了与复合控件相干的其他办法和属性,把握这些成员关于开辟复合控件也很主要。上面枚举了这些罕见办法和属性。
・protectedvirtualvoidEnsureChildControls()
该办法用于断定服务器控件是不是包括子控件。假如不包括,则创立子控件。该办法起首反省ChildControlsCreated属性确当前值。假如此值为假,则挪用CreateChildControls办法。当必要确保已创立子控件时,将挪用该办法。年夜多半情形下,自界说服务器控件的开辟职员无需重写此办法。假如的确重写了此办法,请按与其默许举动类似的体例来利用。
・publicvirtualControlFindControl(string)
该办法用于在以后的定名容器中搜刮指定的服务器控件。
・publicvirtualboolHasControls()
该办法用于断定服务器控件是不是包括任何子控件。假如控件包括其他控件,则为true;不然为false。因为该办法仅断定是不是存在任何子控件,它能够经由过程同意您制止不用要的Controls.Count属性挪用来改善功能。挪用此属性请求实例化ControlCollection工具。假如没有子级,则创立该工具会华侈服务器资本。
・protectedvirtualvoidDataBindChildren()
该办法是ASP.NET2.0新增内容,其用于将数据源绑定到服务器控件的子控件。这为开辟数据绑定范例的复合控件供应了便当。但是,必要注重的是,在服务器控件上挪用此办法时,此办法不会将数据绑定到控件。若要绑定服务器控件及其一切子控件,请挪用DataBind办法。
・protectedboolHasEvents()
这也是一个ASP.NET2.0新增的办法,其用于前往一个值,该值唆使是不是为控件或任何子控件注册事务。假如注册事务,则为true;不然为false。
・Controls属性
该属性的数据范例为ControlCollection,其用于猎取ControlCollection工具,该工具暗示UI条理布局中指定服务器控件的子控件。其属性值指定服务器控件的子控件汇合。
・NamingContainer属性
该属性的数据范例为Control,其用于猎取对服务器控件的定名容器的援用,此援用创立独一的定名空间,以辨别具有不异Control.ID属性值的服务器控件。
・ChildControlsCreated属性
该属性的数据范例为bool,其用于猎取一个值,该值唆使是不是已创立服务器控件的子控件。假如已创立子控件则为true;不然为false。
<P> 典范使用
上文先容了有关创立复合控件的一些基础常识,上面将经由过程一个典范使用加深读者关于复合控件完成办法的了解,其重点放在针对复合控件的出现办法上。
多半控件出现经由过程重写Render办法完成,但是,在复合控件中则年夜有分歧。复合控件由多个子控件组合而成,其出现逻辑是由子控件供应的。
据此,在多数较为复杂的情形下,复合控件不必重写Render办法,比方,创立一个包括文本框和按钮的复合控件,这时候,只需经由过程类撰写的办法在CreateChildControls中增加相干控件便可,而无需Render办法。可是,在多半情形下,复合控件中既包括子控件,又包括用于格局化和结构的HTML。
针对这类情形,假如只接纳类撰写的完成办法,那末很简单形成毛病,而且天生的复合控件功能遭到很年夜影响。最好的办理办法是重写CreateChildControls办法,同时也重写Render办法。在CreateChildControls办法中,为复合控件增加子控件;在Render办法中,为HTTP输入流增加用于格局化和结构的HTML。
上面枚举了出现复合控件的关头步骤:
・控件基类承继自CompositeControl基类。这是在ASP.NET2.0中创立复合控件的关头地点。
・重写CreateChildControls办法,完成实例化、初始化子控件,而且将子控件增加到控件汇合中。
・重写ICompositeControlDesignerAccessor接口的RecreateChildContrls办法。
・假如复合控件中存在用于格局化和结构的HTML,那末倡议将这些内容写进Render办法中,而不要在CreateChildControls办法中创立和增加所需的LiteralControl实例。别的,在增加相干HTML代码过程当中,为了让子控件利用默许天生办法,必需使每一个子控件挪用RenderControl办法。
为了便于读者更好的了解以上内容,上面举例申明。在此示例中,Register控件利用子控件创立用户界面(UI),用于输出用户信息,以向网站注册。此用户界面包含两个TextBox控件(一个用于输出用户名,另外一个用于输出用户的电子邮件地点)和一个用于提交信息的Button控件。Register还将RequiredFieldValidator控件与两个TextBox控件联系关系起来,以确保用户输出了称号和电子邮件地点。复合控件Register源代码以下所示:
usingSystem;
usingSystem.ComponentModel;
usingSystem.Drawing;
usingSystem.Security.Permissions;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
namespaceWebControlLibrary{
[
DefaultProperty("ButtonText"),
ToolboxData("<{0}:Registerrunat="server"></{0}:Register>"),
]
publicclassRegister:CompositeControl{
//界说公有字段
privateButtonsubmitButton;
privateTextBoxnameTextBox;
privateLabelnameLabel;
privateTextBoxemailTextBox;
privateLabelemailLabel;
privateRequiredFieldValidatoremailValidator;
privateRequiredFieldValidatornameValidator;
//完成属性ButtonText
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("按钮上的笔墨内容.")
]
publicstringButtonText{
get{
EnsureChildControls();
returnsubmitButton.Text;
}
set{
EnsureChildControls();
submitButton.Text=value;
}
}
//完成属性Name
[
Bindable(true),
Category("Default"),
DefaultValue(""),
Description("用户名.")
]
publicstringName{
get{
EnsureChildControls();
returnnameTextBox.Text;
}
set{
EnsureChildControls();
nameTextBox.Text=value;
}
}
//完成属性NameErrorMessage
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("用户名考证毛病信息.")
]
publicstringNameErrorMessage{
get{
EnsureChildControls();
returnnameValidator.ErrorMessage;
}
set{
EnsureChildControls();
nameValidator.ErrorMessage=value;
nameValidator.ToolTip=value;
}
}
//完成属性NameLabelText
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("用户名文本框旁的笔墨.")
]
publicstringNameLabelText{
get{
EnsureChildControls();
returnnameLabel.Text;
}
set{
EnsureChildControls();
nameLabel.Text=value;
}
}
//完成属性Email
[
Bindable(true),
Category("Default"),
DefaultValue(""),
Description("邮件地点.")
]
publicstringEmail{
get{
EnsureChildControls();
returnemailTextBox.Text;
}
set{
EnsureChildControls();
emailTextBox.Text=value;
}
}
//完成属性EmailErrorMessage
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("邮件地点考证毛病信息.")
]
publicstringEmailErrorMessage{
get{
EnsureChildControls();
returnemailValidator.ErrorMessage;
}
set{
EnsureChildControls();
emailValidator.ErrorMessage=value;
emailValidator.ToolTip=value;
}
}
//完成属性EmailLabelText
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("电子邮件文本框旁的笔墨.")
]
publicstringEmailLabelText{
get{
EnsureChildControls();
returnemailLabel.Text;
}
set{
EnsureChildControls();
emailLabel.Text=value;
}
}
//重写ICompositeControlDesignerAccessor接口的RecreateChildContrls办法
protectedoverridevoidRecreateChildControls(){
EnsureChildControls();
}
//重写Control基类的CreateChildControls办法
protectedoverridevoidCreateChildControls(){
//扫除一切子控件
Controls.Clear();
nameLabel=newLabel();
nameTextBox=newTextBox();
nameTextBox.ID="nameTextBox";
nameValidator=newRequiredFieldValidator();
nameValidator.ID="validator1";
nameValidator.ControlToValidate=nameTextBox.ID;
nameValidator.Text=NameErrorMessage;
nameValidator.Display=ValidatorDisplay.Static;
emailLabel=newLabel();
emailTextBox=newTextBox();
emailTextBox.ID="emailTextBox";
emailValidator=newRequiredFieldValidator();
emailValidator.ID="validator2";
emailValidator.ControlToValidate=emailTextBox.ID;
emailValidator.Text=EmailErrorMessage;
emailValidator.Display=ValidatorDisplay.Static;
submitButton=newButton();
submitButton.ID="button1";
this.Controls.Add(nameLabel);
this.Controls.Add(nameTextBox);
this.Controls.Add(nameValidator);
this.Controls.Add(emailLabel);
this.Controls.Add(emailTextBox);
this.Controls.Add(emailValidator);
this.Controls.Add(submitButton);
}
//重写Render办法
protectedoverridevoidRender(HtmlTextWriterwriter){
AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,"1",false);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameLabel.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameTextBox.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameValidator.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailLabel.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailTextBox.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailValidator.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2",false);
writer.AddAttribute(HtmlTextWriterAttribute.Align,"right",false);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
submitButton.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write("");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
}
}
以上枚举了复合控件类Register的源代码。固然代码有些冗杂,但是仍是对照简单了解的。下枚举了Register类布局图。
类布局图
如并分离代码可知,Register类承继自CompositeControl基类,实在现了7个属性和3个办法。属性包含ButtonText、Email、EmailErrorMessage、EmailLabelText、Name、NameErrorMessage和NameLabelText。这些属性经由过程定名,信任读者基础能够懂得其意义。
<P> 别的,Register类中重写了来自分歧工具的3个办法。
(1)Render办法从属于Control基类,在本例中次要在该办法中界说了一些与控件结构相干的HTML等外容。
(2)CreateChildControls办法从属于Control基类。在本示例中经由过程重写该办法,完成了将子控件增加到复合控件树中的义务。请读者切记:每当必要Controls汇合时,比方,在数据绑按期间(假如合用),服务器控件布局城市依附对CreateChildControls的挪用。为此,必需在CreateChildControls办法中增加子控件。
(3)RecreateChildControls办法来自CompositeControl基类的ICompositeControlDesignerAccessor接口。经由过程完成这个办法可以使复合控件的计划器能够在计划时从头创立该控件的子控件。
上面枚举了为测试Register控件而创立的Default.aspx页面源代码。
<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Default.aspx.cs"Inherits="_Default"%>
<%@RegisterTagPrefix="Sample"Assembly="WebControlLibrary"Namespace="WebControlLibrary"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>完成复合控件出现</title>
</head>
<body>
<formid="form1"runat="server">
<div>
<Sample:Registerid="demo1"runat="server"ButtonText="注册"EmailLabelText="电子邮件"NameLabelText="用户名"EmailErrorMessage="不克不及为空"NameErrorMessage="不克不及为空"/>
</div>
</form>
</body>
</html>
示例效果如所示。
使用程序最终效果
如所示,复合控件Register在页面中显现了文本、文本框、按钮等,同时,还供应了输出考证功效。但是,当用户单击“注册”按钮以后,即便在用户名和电子邮件的输出都经由过程考证的情形下,页面仍旧没有激发响应的事务处置程序。这是因为在本例中没有完成按钮的事务处置内容。有关复合控件的事务完成将在随后的文章中举行具体解说。
小结
复合控件是经由过程将其他控件聚合在某一公用API下创立而成的控件。复合控件将保存本人子控件的举动实例,而且不但限于出现这些实例。利用复合控件能够带来几点优点,比方能够简化对事务和回发的处置。但是,本文并没有对复合控件的事务完成等相干内容举行解说,请读者持续存眷本系列的随后文章。你觉得学习.NET怎么样,我懂的少,问的可能很幼稚,见笑了啊:) |
|