一切福田,不離方寸,從心而覓,感無不通。

Category Archives: Asp.net

Asp.net控件开发学习笔记(七)—-WebControl基类

  WebControl基类 在Asp.net控件开发中,WebControl基类给我们提供了对于控件的Style更加灵活的解决方案,因为在System.Web.UI.Control基类中只能手动的输入呈现在客户端的代码,但如果开发的服务器控件对style的要求较高。那Control基类的局限性就显而易见了,而继承WebControl类作为基类将会是很好的选择。      System.web.UI.WebControls.Webcontrol直接继承与Control类。在继承了Control的特性的基础上,WebControl基类不仅在生成客户端html使用了另一种更好的render方式,并且还提供了对于老版本浏览器的兼容。   WebControl的ControlStyle属性    ControlStyle属性其实是System.Web.UI.WebControls.Style的一个实例,这个属性用于读取或者设置常用的CSS类,以下是System.Web.UI.WebControls.Style的属性和CSS属性的对应关系。 Style的属性 CSS标准属性 BackColor background-color BorderColor border-color BorderStyle border-style BorderWidth border-width CssClass CSS的类名 Font Font weight, style, family, and so on ForeColor color Height height width width   而在ControlStyle.Font是一些设置字体的属性,是System.Web.UI.FontInfo对象的实例。和标准CSS属性的对照如下表:   Font 属性 CSS标准属性 Bold font-weight: bold Italic font-style: italic Name font-family Names font-family Overline text-decoration: overline Underline text-decoration: underline Size font-size Strikeout text-decoration: line-through   WebControl基类ControlStyle属性的简化 下面这行代码: webcontrol.ControlStyle.BorderWidth = 1; 和      webcontrol.BorderWidth = 1; 代码是等价的,WebControl基类可以不通过ControlStyle属性而访问ControlStyle内的成员,这样在前台可以直接对控件进行style设置,刚才的后台代码于如下前台代码是等价的: <cc:WebControlid="WebControl"runat="server"borderwidth="1"/>   WebControl的Style属性 因为ControlStyle属性只暴露了一部分可用于操控CSS的属性,而除了上述ControlStyle暴露的基本的CSS属性设置之外,WebControl基类还为我们提供了Style属性用于对CSS进行精确完整的操作,可以用如下图让概念更加清晰:     Style属性是System.Web.UI.CssStyleCollection这个类的实例,style属性大多在.aspx文件中用到,比如: <asp:ButtonID="Button1"runat="server"Text="Button"style="background:blue;"/> 而与上面对Style赋值等价的后台代码则是: Button1.Style["background"] = "blue"; 或者 Button1.Style.Add("background", "blue");   一个新的Render系统 和集成Control并重写Render方法不同,WebControl给我们提供了一个新的系统用于Render控件。下面写一个Label的Demo:   Demo:label控件 代码如下:     [ToolboxData("<{0}:label runat=server></{0}:label>"),DefaultProperty("Text")] publicclassLabel : WebControl     { public Label(): base(HtmlTextWriterTag.Span)         {         } publicvirtualstring Text         { get             { object text = ViewState["Text"]; if (text == null) returnstring.Empty; […]

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(六)—-数据回传

  在Asp.net中,利用Http Post的回传机制意味着可以再客户端存储状态并且可以在服务器接收.Asp.net中大部分控件都提供了存储自身状态的功能并且在自身状态改变时引发对应事件。IPostDataHandler接口提供了在服务器处理客户端通过Http Post回传数据的方法。   IPostDataHandler 通过实现IPostDataHandler接口,服务器可以在不使用Page和Request对象的情况下来读取客户端回传数据。IPostDataHandler还提供了在用户状态改变的情况下来引发相应事件的框架。IPostDataHandler的定义如下: publicinterfaceIPostBackDataHandler     { publicbool LoadPostData(string postDataKey,         NameValueCollection postCollection); publicvoid RaisePostDataChangedEvent(); }   对于LoadPostData函数,如果返回值为true,则会引发下面的RaisePostDataChangeEvent方法。这个方法中我们可以加入需要引发的事件,比如: publicvirtualvoid RaisePostDataChangeEvent()     {         OnTextChanged(EventArgs.Empty); } 这个方法有两个参数,先说第二个参数,第二个参数返回键值对,key(键)是控件的unique id,这个id是通过客户端的id来决定的,大多数情况下,这两个id相等,比如客户端的<input id=”xx” runat=”server” />则在服务端的unique id也会是”xx”,但是如果控件放在gridview或者masterpage里的话,uniqueid会是母控件的uniqueid+分隔符+子控件的uniqueid.而value(值)则是对应控件的回传数据。比如下图: 在页面只有两个控件,TextBox控件和Button控件,前两个是asp.net内置的ViewState和验证。而第三个是id名为”cc”的TextBox,第四个是id为Button1的button.则可以看出postCollection参数其实是页面所有实现了IPostBackDataHandler接口的回传数据,而第一个参数postDataKey则是这个方法所属控件的uniqueid. 所以可以这样来获得本控件这一次的回传数据: postCollection[postDataKey] 当然也可以获得其他控件这一次的回传数据以达到和其它控件的交互,比如: postCollection[3]   下面通过一个Demo来展示IPostDataHandler   DEMO1  自己写一个拥有状态的TextBox控件 通过这个Demo可以更清楚的让我们明白ViewState和PostBack Data之间通过实现IPostDataHandler的交互。 代码如下: [ToolboxData("<{0}:textboxDemo runat=server></{0}:textboxDemo>")] publicclassTextboxDemo : Control, IPostBackDataHandler     { string _text; publicvirtualstring Text         { get             { object text = ViewState["Text"]; if (text == null) returnstring.Empty; else return (string)text;             } set             {                 ViewState["Text"] = value;             }         } publicbool LoadPostData(string postDataKey,NameValueCollection postCollection)         {             Text = postCollection[postDataKey]; returnfalse;         } publicvirtualvoid RaisePostDataChangedEvent()         {         } overrideprotectedvoid Render(HtmlTextWriter writer)         {             Page.VerifyRenderingInServerForm(this); base.Render(writer); //输出 <INPUT type="text">标签             writer.Write("<INPUT type=""text"" name=""");             writer.Write(this.UniqueID);             writer.Write(""" value=""" + this.Text + """ />");         } } 这是一个简单的TextBox实现。通过实现IPostBackDataHandler接口,我们可以在每次回传到服务器后保存TextBox的状态.即TextBox的Value的值. 注意在Render方法里有:Page.VerifyRenderingInServerForm(this);,这行代码表示此控件必须在<form>标签内,如果不在此标签内,则会报错.所有需要实现数据回传的控件最好都要使用这个方法. TextBoxDemo控件的使用方法这里就不再累述了。   ASP.net控件状态 在asp.net 2.0以后的版本。可以通过设置控件的EnableViewState属性来控制单个控件是否保存其状态。在一些访问量比较大的网站上,如果不注意关闭不需要的ViewState,则用户在每回提交时都会导致传送额外的ViewState字符串,这回导致性能问题. 控件的状态还有一个很棒的特性是在即使ViewState被禁用的情况下,控件的状态保持依然可用. http://www.cnblogs.com/CareySon/archive/2009/10/09/1579781.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(五)—Asp.net客户端状态管理

  Asp.net提供了很多种与客户端状态交互的方式,控件开发人员可以给控件添加额外的值(比如控件的ViewState)来使控件貌似能记住前一个值.Asp.net提供了四种客户端状态管理的方式。他们是: l ViewState l URL strings l Hidden Html Variables l Cookies   URL String 利用URL传值请求服务器是简单并且应用最广泛的。比如在电子商务中,一个像这样的地址: http://xxx.com/product.aspx?categoryid=1&productid=1 表示传入两个键值对。 在服务器接收对应值时可以用Request对象的QueryString属性和Params属性来进行访问,也可以利用Request本身的索引器来访问,比如Request[“category”]。 注意:QueryString属性只能访问以GET方式传的值.   Cookies Cookies是一个通过在Http协议中添加额外的信息让服务器和客户端共同实现在用户的机器上存储一定量的信息.Cookies里存放的信息针对特定站点,并且有时间限制。这意味着Cookies在一个站点存放的信息只能这个站点读取,而不能在其他站点被读取。    Cookies的信息是通过Http头里发送Set-Cookies然后加上服务器想在客户端存储的信息. 在Asp.net中对Cookies的操作是通过HttpResponse类的Cookies属性. 给客户端的Cookies赋值的代码如下: Response.Cookies["LastVisit"].Value = DateTime.Now.ToShortDateString();          Response.Cookies["LastVisit"].Expires = DateTime.Now.AddDays(1); 这两行代码会在Http头中传送到客户端服务器,HTTP会如下:        Set-Cookie: LastVisit=mm/dd/yy; path=/ 当在对此代码进行读取时,只需要利用Request对象中的Cookies属性,代码如下 string firstname = Request.Cookies["LastVisit"].Value;   在Cookies中,不要存储大量信息.在控件开发的过程中,尽量不要使用Cookies,因为Cookies可能被客户端浏览器禁用.   HTML Hidden variables Html hidden variable也是被经常使用的客户端状态存储方式,在这种方式相对于前两种方式的优势在于,这种方式没有传送字节的大小限制,并且不用怕客户端浏览器不支持(啥?难道有不支持HTML的浏览器???) 利用Http Post方法,可以将客户端的Hidden variable回传到服务器.Asp.net通过System.Web.UI.HtmlControls.HtmlInputForm服务器控件,这个控件会在页面中产生如下代码: <formid="first"method="post"runat="server"> 而当render到客户端时,会产生如下代码 <formid="first"method="post"action=”first.aspx”> 注意,first.aspx就是指向页面本身   再来看一个完全点的例子: <formid="first"method="post"runat="server"> <inputtype="text"value="CareySon"id="name"/> <inputtype="text"value="Write Code"id="Task"/> </form>   当上面的form被提交时,或者利用javascript来提交时,asp.net会将当前所有的input格式化成字符串以便服务端进行提取.上面的代码格式化成字符串时会变成: Name=CareySon&Task==Write Code 而在服务器端进行读取时,可以使用Request对象的Form属性索引器或者Params属性索引器: string name = Request.Form["name"]; string task = Request.Params["task"];   Asp.net的回传机制也可以用下图表示: 剑是双刃的,当然Hidden Form也并不是只有好处。比如Hidden Form的值虽然不显示在网页中,但是依然可以被用户查看,所以不要在Hidden Form里存放敏感信息,否则必须的进行字符串加密.还有当Hidden Form中存放的值过大时,会有一些潜在的性能问题.因为每次进行Post提交的时都会将所有的Hidden Form提交的服务器L 当然,虽然有一些缺点,但Hidden Form还是在控件开发中储存状态信息的比较好的方式.   ViewState  ViewState的本质其实就是在Hidden Form上抽象出一层,换句话说,ViewState的存储原理其实就是利用了Hidden Form.ViewState。克服了Hidden Form一些硬性弱点,比如ViewState会对Hidden Form里的值进行压缩,编码使减少传输的大小并使客户端无法查看Hidden Form里的值。在本质上ViewState就是如下一个Hidden Form: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value=" " /> ViewState还有一个比较有用的作用是用于存储控件状态.即存储与控件有关的数据.ViewState是System.Web.UI.StateBag类的实例,而StateBag实现了很多的接口,如下: 接口 描述 ICollection Defines enumerators, synchronization methods, and size for collections IDictionary Specialized collection interface that implements a collection of name/value pairs IEnumerable Provides the enumerator for iteration over a collection IStateManager Defines the properties and methods required to support ViewState management in server controls 其中最有趣的是IStateManager接口.StateManager实现了这个接口用于存储和载入控件的ViewState. .net Framework利用ISateManager对控件的ViewState在被序列化并存入名称为_viewstate的Hidden Form中之前进行精简. 在ViewState的状态信息中存储着以键/值对方式存储的控件信息,(包括当前页面,因为System.Web.UI.Page也是继承于System.Web.UI.Control的)。在页面执行过程中.ViewState会被Hash运算和压缩.最终存入名称为_ViewState的Hidden Form中。此外,ViewState能够防止修改,任何在Asp.net页面处理周期之外对ViewState的修改都会被Asp.net发现并且做出处理。   简单的使用 ViewState听起来很复杂,但是使用起来却非常简单.对ViewState赋值的时候只需要: ViewState["Task"] = "Write Code"; 上面的代码在客户端生成的时候会生成如下代码: <inputtype="hidden"name="__VIEWSTATE"id="__VIEWSTATE"value="/wEPDwULLTE2MTY2ODcyhc2spkL8ufmlbb5xWbI/"/>   对ViewState的读取也是类似的方法.代码如下: string task = ViewState["Task"].ToString();   页面中的ViewState在很多时候会很庞大,这大大加重了服务器负担。所以开发人员需要将不需要ViewState的控件的EnableViewState设置成false,这个属性时System.Web.UI.Control的,这意味着所有的控件都具有这个属性. http://www.cnblogs.com/CareySon/archive/2009/10/04/1577948.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(四)—Asp.net服务端状态管理

  Asp.net请求处理构架   当一个客户端浏览器对IIS发起访问请求资源时(比如一个.aspx文件),Asp.net会初始化并维护一个包含了多个Response和Request的Http Session 的客户端的连接。一次典型的访问如下图:    上图中,首先,一个请求发到IIS服务器,IIS会检查请求的扩展名,如果是aspx或者ascx文件,IIS会自动匹配到aspnet_isapi.dll来处理这个请求,如果是其他扩展名的文件,IIS会自动匹配到对应ISAPI文件来处理请求。 请求的过程会执行HttpRuntime对象,而HttpRuntiem会利用HttpApplicationFactory对象来确认当前的AppDomain并创建HttpApplication对象来处理请求。Global.asax处理的事件就是基于HttpApplication对象存在的事件。在当前Application中,当前用户的用户信息会通过HttpApplication对象的Context进行访问.接下来执行过程到了HttpModule,任何执行HttpModule的类在这时都会在程序中注册并引发他们的事件。比如Global.asax中的全局事件Session_Start和Session_End事件其实就是SessionStateModule,它实现了HttpModule.所以HttpModule的作用是实行全局的功能. 当HttpModule执行完成后,会到HttpHandler这一块,不同的请求会调用不同的HttpHandler,HttpHandler的执行方法是调用其内部的ProcessRequest()方法,ProcessRequest()方法只有一个参数,参数类型为保存了当前用户状态的HttpContext对象。然后,HttpHandler会负责利用Context.Response.Write()方法来响应当前的请求. 上面的整个处理过程都是利用了Asp.net的对对象,这些对象的关系可以简单用下图表示:     HttpHandler HttpHandler是Asp.net的处理.aspx和.asmx的构架和方法.HttpHandler允许用户在应用程序处理单个的Url或者相同的扩展名.Asp.net里面有两个Build-in的HttpHandler,如下: Handler 描述 Asp.net Web Service 默认用于处理.asmx的HttpHandler Asp.net 页面 默认用于处理.aspx的HttpHandler   注意,上面的描述中用了默认,这意味这我们也可以写自己的处理.asmx或.aspx的HttpHandler实现      Asp.net的PageHandlerFactory是用来专门为创建用于被Developer操作的Page实例的,在这个实例中会包含我们常用的用户信息,比如Session,Application,ViewState等……. 通常情况下,HttpHandler可以是异步的,也可以使同步的。 同步的过程是指处理完整个Http请求才返回数据,而异步指处理完请求立刻返回数据.   Asp.net和服务端状态管理 Asp.net服务端状态管理是由我们最熟悉的Application和Session对象组成的,它们以集合的方式将用户信息储存在服务器. Application是面向全局的,而Session对象是针对特定用户的.这两个对象都可以通过HttpContext对象来进行访问。   HttpContext对象 HttpContext提供了服务端状态管理并实现了HttpApplicationState和HttpSessionState,下面是一些HttpContext对象的属性:     AllErrors Gets an array of errors accumulated while processing an HTTP request.   Application Gets the HttpApplicationState object for the current HTTP request.   ApplicationInstance Gets or sets the HttpApplication object for the current HTTP request.   Cache Gets the Cache object for the current application domain.   Current Gets or sets the HttpContext object for the current HTTP request.   Error Gets the first error (if any) accumulated during HTTP request processing.   Handler Gets or sets the IHttpHandler object responsible for processing the HTTP request.   Items Gets a key/value collection that can be used to organize and share data between an IHttpModule interface and an IHttpHandler interface during an HTTP request.   PreviousHandler Gets the IHttpHandler object for the parent handler.   Profile Gets the ProfileBase object for the current user profile.   服务端状态管理总结 通常情况下,在开发服务器控件时,尽量少用服务端的状态管理,尤其是在能够使用客户端状态管理时,就不要用服务端状态管理。但在一些情况下,客户端浏览器被限制,比如cookies被禁止,这时使用服务端状态管理还是比较方便的J http://www.cnblogs.com/CareySon/archive/2009/10/03/1577745.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(三)-控件开发基础

 封装 在asp.net中,控件被分为两类.用户控件和自定义服务器控件。前者就是我们经常用来将一些可复用的内容封装成的.ascx文件。这里主要研究后者.   创建自定义服务器控件 创建自定义控件的第一步是选择以哪一个类作为基类来创建控件,Asp.net最常见的几个基类罗列如下: l System.Web.UI.Control:这是所有控件的基类,所有作为控件的类都必须直接或者间接的继承此类,此类仅仅提供最少量的属性和方法。 l System.Web.UI.WebControls.WebControl:这个类继承于Control类,在实现控件最基本的属性和方法后,又额外提供了控件CSS样式相关的一系列属性。如果是UI控件,那肯定就选它了. l System.Web.UI.WebControls.Webpart:这个不用说了,看名字就知道是提供了WebPart相关的功能. l System.Web.UI.WebControls.CompositeControl:如果需要创建复合控件(即那些控件内部还有其他控件,比如Calender),选择这个类作为基类. l System.Web.UI.WebControls.DatabindingControl:用于作为数据源相关控件的基类。 l System.Web.UI.WebControls.CompositeDatabindingControl:这个基类可以看做上面两个基类的结合,提供了上面两个基类的功能,GridView就是继承自这个基类.   简单控件Or复合控件 先来了解一下简单控件和复合控件的定义:   简单控件:那些直接生成(render)对应HTML的控件,比如Botton和TextBox控件. 复合控件:如何生成HTML依赖于其子控件,比如Reperater,FormView.   下面的图示会让概念更加清晰:      简单控件是那些比较简单的更加,往往是一个控件对应一个HTML标签.但缺点显而易见,就是当面对大量HTML代码片段时,就会显得更加难以维护. 复合控件在面对大量HTML代码片段时就显得游刃有余了,在遵守了面向对象抽象和封装的原则上,复合控件的维护性和易用性都不错.   Demo:创建一个简单的服务器控件: 这里我们创建一个简单的菜单自定义服务器控件。通过继承最基础的System.Web.UI.Control基类。然后覆盖Render方法来达到自定义输出的目的,代码如下:   namespace SimpleControl { [ToolboxData("<{0}:menucustomcontrol runat=server></{0}:menucustomcontrol>")] publicclassMenuCustomControl : Control     { protectedoverridevoid Render(HtmlTextWriter writer)         { base.Render(writer);             writer.WriteLine("<div>");             RenderMenuItem(writer, "网易", "http://www.163.com");             writer.Write(" | ");             RenderMenuItem(writer, "新浪", "http://www.sina.com");             writer.Write(" | ");             RenderMenuItem(writer, "MSDN", "http://msdn.microsoft.com");             writer.Write(" | ");             RenderMenuItem(writer, "ASP.NET", "http://asp.net");             writer.WriteLine("</div>");         } privatevoid RenderMenuItem(HtmlTextWriter writer, string title, string url)         {             writer.Write("<span><a href=""");             writer.Write(url);             writer.Write(""">");             writer.Write(title);             writer.WriteLine("</a><span>");         }     } } 通过HtmlTextWriter类,我们可以在控件原有的基础上,加入我们自己想加入的内容,注意base.Render(writer);方法,通过调用父类的Render方法,我们可以再实现父类的基础上,加入我们额外的内容(很像设计模式里的装饰模式)   控件使用方法: Ok,控件完成了.使用方法很简单,只需要在页面头部添加如下代码引入控件即可: <%@RegisterTagPrefix="sc"Namespace="SimpleControl"%> 在使用时就像使用用户控件一样,在页面注册完成后,系统会自动搜索命名空间内的直接或间接继承于Control基类的控件,在前台使用时,会自动出现智能提示: 代码如下: <sc:MenuCustomControlrunat="server"></sc:MenuCustomControl> 页面执行,效果如下:           Demo2:继承现有控件   在很多情况下,我们并不需要重新发明轮子,我们可以通过继承来利用现有控件的特性并额外添加我们需要的功能达到复用的目的.先看一下效果:    通过继承TextBox控件,并添加额外的Enable3d属性,使现有控件拥有额外的属性。前台代码摘录如下: 我是3D的:<sc:TextBox3drunat="server"></sc:TextBox3d><br/> 我不是:<sc:TextBox3drunat="server"Enable3D="false"></sc:TextBox3d>   后台代码如下: [ToolboxData("<{0}:textbox3d runat=server></{0}:textbox3d>")] publicclassTextBox3d : TextBox// 继承自TextBox     { public TextBox3d()         {         Enable3D = true;         } publicbool Enable3D         { get             { object enable3D = ViewState["Enable3D"]; if (enable3D == null) returnfalse; else […]

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(二)-控件开发基础

  接上篇……..   通过查看System.Web.UI.HtmlControls命名空间,我们可以发现,很多HTML对应的标签都可以通过添加runat=”server”属性转化为服务器控件,比如<table>会转化为HtmlTable对象,但像<input >标签可以通过type属性对应不同的服务器对象。当html内的标签没有和上图中的服务器控件匹配时,所有不匹配的html标签都会通过添加runat=”server”转化为HtmlGenericControl服务器控件。下面是对应的服务器控件类与HTML标签之间的对应关系:   HTML Tag HTML Server Control <form> HtmlForm <input type="text"> HtmlInputText <input type="password"> HtmlInputText <input type="radio"> HtmlInputRadioButton <input type="checkbox"> HtmlInputCheckBox <input type="submit"> HtmlInputButton <input type="hidden"> HtmlInputHidden <input type="button"> HtmlInputButton <input type="image"> HtmlInputImage <input type="file"> HtmlInputFile <button> HtmlButton <select> HtmlSelect <textarea> HtmlTextArea <img> HtmlImage <a> HtmlAnchor <table> HtmlTable <tr> HtmlTableRow <td> HtmlTableCell 其他标签 HtmlGenericControl       Demo:动态构建html表格   通过在前台设置表格的行(x)和列(y),动态的利用System.Web.UI.HtmlControls命名空间下的控件动态的进行设置表格的大小: 前台代码如下: <h3>HTML Controls</h3> X <inputtype="text"id="XTextBox"runat="server"/><br/> <br/> Y <inputtype="text"id="YTextBox"runat="server"/><br/> <br/> <inputtype="submit"id="BuildTableButton"runat="server" value="Build Table"onserverclick="BuildTableButton_ServerClick"/><br/> <br/> <spanid="Span1"runat="server"></span> </div> 后台代码如下: protectedvoid BuildTableButton_ServerClick(object sender, EventArgs e)     { int xDim = Convert.ToInt32(XTextBox.Value); int yDim = Convert.ToInt32(YTextBox.Value);         BuildTable(xDim, yDim);     } privatevoid BuildTable(int xDim, int yDim)     { HtmlTable table; HtmlTableRow row; HtmlTableCell cell; HtmlGenericControl content;         table = newHtmlTable();         table.Border = 1; for (int y = 0; y < yDim; y++)         {             row = newHtmlTableRow(); for (int x = 0; x < xDim; x++)             {                 cell = newHtmlTableCell();                 cell.Style.Add("font", "18pt");                 cell.Style.Add("background-color", "blue");                 cell.Style.Add("color", "red"); […]

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记-控件开发基础(一)

  服务器控件开发基础 当开发一个服务器控件时,首先要明白其内部的工作机理。其实在页面内部每一点由asp.net返回的HTML代码无论是简单的<span>标签,或者是button按钮,或者是复杂的gridview控件,都是由继承自System.Web.UI.Control的对象生成的。   控件的属性 控制控件的方法大多是通过控件的属性来操作的,通过控制服务器控件的属性,就可以相应的改变服务器生成的html. 下面是一个服务器控件的属性:    在Visual Studio里,当通过属性窗口来改变控件的属性时,VS会自动将属性添加到对应的aspx的HTML里,而在html内添加属性时,在属性窗口里也会对应显示更改过的属性视图比如: <asp:ButtonID="Button1"runat="server"Text="Button"CommandName="cName"/> 在属性窗口里会对应显示,如下图:        当然某些控件的属性会略有不同,比如常用的Label控件: <asp:LabelID="Label1"runat="server">这里是Text属性</asp:Label> 在开始符号和结束符号之间的内容会被设置成Text属性.   当然,最实用也是我们最常用的是通过C#以编程的方式动态的修改控件的属性.这就不说了.   控件的方法 控件通过方法来操作更加复杂的控件操作,通常在控件的方法内部会有很复杂的过程,一般包括几个内部函数和属性的组合.比如: privatevoid LoadDropDownList() { ArrayList list = new ArrayList(); list.Add("Hello"); list.Add("Goodbye"); GridView1.DataSource = list; GridView1.Databind(); } 这样,通过调用Databind()方法,就可以讲gridview和数据源进行绑定. 控件的事件 控件通过事件来通知其它类或者客户端其内部的某个状态被改变。事件是一种灵活的机制,当控件与客户端进行交互的时候,事件会通过Http Post方法和服务器进行交互,通过自动回传机制,WEB开发中的事件表现起来就会像开发Windows FORM程序一样(当然,速度是无法和Form相比的) 在Visual Studio中,可以在属性窗口中通过黄色的闪电图标来显示和控制控件的事件,如下:   当双击相应的事件后,会在后台产生默认的处理方法,命名规则为”控件名_事件名”           WEB Page本质是一个控件树   在aspx页面的头部将Trace="true"设置到Page后,页面会显示相应的追踪信息,在Control Tree那一节,你会发现整个页面其实就是一个控件树,如图:          根控件? OK,既然asp.net页面的本质是一个控件树,按照C#是完全面向对象的语言惯例(所有的一切都是继承于System.Object),那么所有控件共同的父类是什么? 在asp.net中,所有的控件被分布在3个主要命名空间中,分别为:    System.Web.UI    System.Web.UI.WebControls    System.Web.UI.HtmlControls 它们之间的关系如下图所示     System.Web.UI命名空间 由上图可知,System.Web.UI处于继承树顶端的,而System.Web.UI.Control是所有控件的基础,所有的控件必须强制直接或者间接的继承Control类,而直接继承Control类的是Page类,以及UserControl类。   System.Web.UI.HtmlControls命名空间 在System.Web.UI.HtmlControls命名空间中的对象,通过在html标签中加入runat=”server”属性,能够将HTML中的标签转化为服务器控件。Asp.net的引擎会将的页面中的HTML标签和System.Web.UI.HtmlControls内的对象进行匹配。System.Web.UI.HtmlControls命名空间如图:       未完待续……… http://www.cnblogs.com/CareySon/archive/2009/09/30/1576984.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(5)--添加客户端功能

  随着Ajax等技术的发展,客户端功能也逐渐变得越来越重要。如果在服务器控件中添加客户端功能,将会创作出功能更强大,界面更丰富的服务器控件。 客户端功能: 在Web编程中,客户端功能传统上是由Web页开发人员负责,并且不被封装在服务器组件中。ASP.NET脱离了这一范畴并使服务器控件能够发出客户端脚本,从而使服务器控件能够将客户端处理与服务器端处理结合起来。例如按钮控件的OnClientClick属性,就可以在其中声明一段脚本在客户端执行。 OnClientClick—>return confirm('Hello Word'),单击按钮时就会在客户端弹出一个提示框。 实现客户端功能的技术主要是客户端脚本(JavaScript、VBScript等)和DHTML。这个想必大家都知道。 ASP.NET服务器控件中客户端功能的实现: 下面我们进入正题,来看看ASP.NET服务器控件中是如何实现客户端功能的:代码如下: namespace ServerClientControl{    [DefaultProperty("Text")]    [ToolboxData("<{0}:SimpleButton runat=server></{0}:SimpleButton>")]publicclass SimpleButton :Button{protectedoverridevoid RenderContents(HtmlTextWriter output){        }protectedoverridevoid AddAttributesToRender(HtmlTextWriter writer){base.AddAttributesToRender(writer);            writer.AddAttribute("onclick", "window.confirm('Hello World! ');");        }    }} 我们创建一个继承自Button的类,通过AddAttributesToRender()方法添加一个onclick客户端事件。这样就简单的实现了向服务器控件添加客户端事件的功能。 ClientScriptManager 类 当然,这只是简单的方式。在 .NET Framework 2.0 版中为我们新增了ClientScriptManager 类。通过在网页的 HTML 标记中包含脚本,可以声明方式向网页添加客户端脚本。然而,有些情况下需要动态添加客户端脚本。 实现复杂客户端功能有关的几个常用方法:RegisterClientScriptBlock():向页的顶部添加一个脚本块。以字符串形式创建脚本,然后将其传递给方法,方法再将脚本添加到页中。可以使用此方法将任何脚本插入到页中。请注意,脚本可能在所有元素完成之前呈现到页中;因此,您可能无法从脚本中引用页上的所有元素。RegisterClientScriptInclude():与 RegisterClientScriptBlock 方法类似,但此方法将添加引用外部 .js 文件的脚本块。包含文件在任何其他动态添加的脚本之前添加;因此,您可能无法引用页上的某些元素。RegisterStartupScript():向页中添加一个脚本块,该脚本块在页完成加载后引发页的 onload 事件之前执行。该脚本通常不创建为事件处理程序或函数;它通常只包含要执行一次的语句。RegisterOnSubmitStatement():添加响应页的 onsubmit 事件而执行的脚本。该脚本在提交页之前执行,允许您取消提交。IsStartupScriptRegistered():确定Page对象是否注册了启动脚本。  IsClientScriptBlockRegistered():确定Page对象是否注册了客户端脚本。 更详细的说明讲解大家可以参看MSDN。 这里还要提下OnPreRender 方法。这个方法触发PreRender 事件。PreRender 事件在加载 Control 对象之后、呈现之前发生。可以理解为准备呈现的意思。在该事件的生存期内可以保存服务器控件视图状态的任何更改。不保存呈现阶段内所做的同样更改。开发人员可以再这个事件中添加脚本处理。 string JsPath ="js/";//重写OnPreRender方法protectedoverridevoid OnPreRender(EventArgs e){            Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Ajax", "<script language='javascript' src='"+ JsPath +"Ajax.js"+"'></script>");//注册客户端脚本            Page.ClientScript.RegisterStartupScript(this.GetType(),"jQuery", "<script language='javascript' src='"+ JsPath +"jQuery.js"+"'></script>");//注册启动脚本base.OnPreRender(e);        } 这里简单的举个例子,Ajax.js中声明了要调用函数的名称,jQuery中对函数具体的实现。具体功能的代码就根据自己的需求实现啦!本人的js一般,这里就不做例子了。 IScriptControl 接口 IScriptControl接口:定义 ASP.NET 服务器控件为在启用 AJAX 的应用程序中定义JavaScript资源而必须实现的方法。创建将 ASP.NET 的 AJAX 功能用于浏览器中的扩展功能的自定义 Web 服务器控件。 当由类实现时,IScriptControl 接口的方法提供对脚本库的引用,这些脚本库定义客户端组件和表示客户端类型实例的脚本说明符。在将包含脚本控件功能的自定义服务器控件中实现此接口。这样,通过IScriptControl接口也能够实现ASP.NET服务器空间中添加客户端功能。 MSDN上有个通过IScriptControl向Web 服务器控件添加客户端功能的很好的例子。讲解的很详细。感兴趣的朋友可以参看: http://msdn.microsoft.com/zh-cn/asp.net/bb386450.aspx#Mtps_DropDownFilterText 小结:感冒了,就先写到这吧。通过向服务器控件中添加客户端功能,可以很好的增强控件的价值,提高用户客户端的体验。从中我们也不难看出,要想开发出一个好的服务器控件也是满不容易的,不但要对控件的生命周期,.NET提供的类库,接口有所了解,还要对js也要比较熟悉。所以从自定义服务器控件的开发过程中学习到很多知识。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/27/1512248.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(4)--复合控件

  复合控件 概念:     所谓复合控件:简单的理解就是将多个基本的控件组合成一个控件,从而实现自己想要的效果。微软为ASP.NET2.0中推出的登录控件等就是一个复合控件。从功能的实现上,复合式控件有点像用户控件,只是一个是.ascx文件,一个是.dll文件。 呈现简单的复合控件: 要想呈现一个复合控件,需要了解以下几个方面: -->实现INamingContainer接口。 任何实现该接口的控件都创建一个新的命名空间,在这个新的命名空间中,所有子控件 ID 属性在整个应用程序内保证是唯一的。 -->Control.CreateChildControls 方法。 由 ASP.NET 页面框架调用,以通知使用基于合成的实现的服务器控件创建它们包含的任何子控件,以便为回发或呈现做准备。 当开发复合服务器控件或模板服务器控件时,必须重写此方法。重写 CreateChildControls 方法的控件应实现 INamingContainer 接口以避免命名冲突。    -->Control.ChildControlsCreated 属性。 获取一个值,该值指示是否已创建服务器控件的子控件。    -->Control.EnsureChildControls 方法。 确定服务器控件是否包含子控件。如果不包含,则创建子控件。    下面就通过实例来呈现个简单的复合登陆控件:创建ASP.NET服务器控件工程。complexControl。 先来看代码: namespace complexControl{    [DefaultProperty("Text")]    [ToolboxData("<{0}:LoginControl runat=server ButtonText='登录' NameLabel='用户名:' PasswordLabel='用户密码:'></{0}:LoginControl>")]publicclass LoginControl : WebControl, INamingContainer, IPostBackEventHandler{private Button _button;private TextBox _nameTextBox;private Label _nameLabel;private TextBox _passwordTextBox;private Label _passwordLabel;private RequiredFieldValidator _nameValidator;private RequiredFieldValidator _passwordValidator;        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("按钮文本")]publicstring ButtonText{get{                EnsureChildControls();//确定服务器控件是否包含子控件return _button.Text;            }set{                EnsureChildControls();                _button.Text = value;            }        }        [Bindable(true),Category("Default"),DefaultValue(""),Description("姓名")]publicstring Name{get{                EnsureChildControls();return _nameTextBox.Text;            }set{                EnsureChildControls();                _nameTextBox.Text = value;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("必须输入姓名")]publicstring NameErrorMessage{get{                EnsureChildControls();return _nameValidator.ErrorMessage;            }set{                EnsureChildControls();                _nameValidator.ErrorMessage = value;                _nameValidator.ToolTip = value;            }        }        [Bindable(true),Category("Apperance"),DefaultValue(""),Description("姓名标签")]publicstring NameLabel{get{                EnsureChildControls();return _nameLabel.Text;            }set{                EnsureChildControls();                _nameLabel.Text = value;            }        }        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]publicstring Password{get{                EnsureChildControls();return _passwordTextBox.Text;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("必须输入密码")]publicstring PasswordErrorMessage{get{                EnsureChildControls();return _passwordValidator.ErrorMessage;            }set{                EnsureChildControls();                _passwordValidator.ErrorMessage = value;                _passwordValidator.ToolTip = value;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("密码标签")]publicstring PasswordLabel{get{                EnsureChildControls();return _passwordLabel.Text;            }set{                EnsureChildControls();                _passwordLabel.Text = value;            }        }protectedoverridevoid CreateChildControls(){            Controls.Clear();            _nameLabel =new Label();            _nameTextBox =new TextBox();            _nameTextBox.ID ="nameTextBox";            _nameValidator =new RequiredFieldValidator();            _nameValidator.ID ="validator1";            _nameValidator.ControlToValidate = _nameTextBox.ID;            _nameValidator.Text ="*";            _nameValidator.Display = ValidatorDisplay.Static;            _passwordLabel =new Label();            _passwordTextBox =new TextBox();            _passwordTextBox.TextMode = TextBoxMode.Password;            _passwordTextBox.ID ="passwordTextBox";            _passwordValidator =new RequiredFieldValidator();            _passwordValidator.ID ="validator2";            _passwordValidator.ControlToValidate = _passwordTextBox.ID;            _passwordValidator.Text ="*";            _passwordValidator.Display = ValidatorDisplay.Static;            _button =new Button();            _button.ID ="button1";//_button.Click += new EventHandler(_button_Click);            _button.CommandName ="ClickLogin";this.Controls.Add(_nameLabel);this.Controls.Add(_nameTextBox);this.Controls.Add(_nameValidator);this.Controls.Add(_passwordLabel);this.Controls.Add(_passwordTextBox);this.Controls.Add(_passwordValidator);this.Controls.Add(_button);        }protectedoverridevoid Render(HtmlTextWriter writer){            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();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _nameTextBox.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _nameValidator.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderBeginTag(HtmlTextWriterTag.Tr);            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordLabel.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordTextBox.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordValidator.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderBeginTag(HtmlTextWriterTag.Tr);            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");            writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _button.RenderControl(writer);//writer.AddAttribute(HtmlTextWriterAttribute, Page.GetPostBackEventReference(_button));            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            writer.Write("&nbsp;");            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderEndTag();  // Table        }    }} 首先我们实例化了几个现有控件的对象。然后声明了一大堆的属性,要注意的:和平时定义属性不同,我们在每一个属性中都添加了EnsureChildControls ()方法。其他的没有任何变化,和一般的属性声明一样。 接下来我们从写了重要的CreateChildControls()。将前面声明好的实例化控件对象添加到controlcollection中。融合成一个控件。 最后重写控件显示的Render()方法。生成登录窗体的样式。效果如下: 这样,我们基本上就完成了复合控件的基本显示功能。 复合控件的事件处理: 由于复合控件中包含子控件,这就使得复合控件的事件处理变得复杂起来。由于不允许开发人员直接访问子控件,如果子控件的事件不能作为顶级事件引发,那么将无法实现子控件的事件处理。 我们可以以两种形式来完成事件的处理:一是直接将事件封装到控件中,显然灵活性很差。二就是自定义事件,用户来完成事件的代码。 第一种情况比较简单:就是在创建我们得控件时,将要实现的效果直接封装在dll中。这里就不做说明了。 但是往往控件触发时,我们想做自己的事情,这就是第二种情况的事件处理。这就需要把事件交给主控件,由主控件统一暴露事件,这样开发人员在使用控件时仅需要为主控件注册事件即可,剩下的由主控件负责引发子控件的事件或执行子控件的某些功能,这里就涉及主控件与其子控件的事件衔接问题,复合控件的这种事件处理,主要是实现子控件事件上传的过程。一般分为:包含法和冒泡法两种处理方式。 -->包含法: 基本思想是:通过在子控件的事件处理程序中调用复合控件的顶层事件处理程序,以完成子控件的事件上传。 在CreateChildControls方法中,为子控件添加事件处理程序。 接着上面登陆控件的例子,来实现下登录按钮的事件。 首先在CreateChildControls()中,为_button添加单击事件。(其他代码略) _button =new Button();            _button.ID ="button1";             _button.Click +=new EventHandler(_button_Click); 然后创建主控件对外的处理函数: void _button_Click(Object source, EventArgs e){            OnClickLogin(EventArgs.Empty);        }privatestaticreadonlyobject EventClickLogin =newobject();publicevent EventHandler ClickLogin{            add{                Events.AddHandler(EventClickLogin, value);            }            remove{                Events.RemoveHandler(EventClickLogin, value);            }        }protectedvirtualvoid OnClickLogin(EventArgs e){            EventHandler clickLoginHandler = (EventHandler)Events[EventClickLogin];if (clickLoginHandler !=null){                clickLoginHandler(this, e);            }        }publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件{            OnClickLogin(new EventArgs());        } 事件的详细处理请参看上一篇。这里要说明的是:在按钮的单击事件处理函数中,将我们在主控件中声明的事件传入进去: void _button_Click(Object source, EventArgs e){     OnClickLogin(EventArgs.Empty);} 这样,我们就实现了第一种方法。测试一下: protectedvoid LoginControl1_ClickLogin1(object sender, EventArgs e){     Label1.Text ="sssssssssssssssqwwssss";} 单击按钮,将触发上面的事件。 -->冒泡法: 基本思想:使用ASP.NET 2.0框架提供的事件上传机制。这种机制允许子控件将事件沿其包容层次结构向上传播到合适的位置引发,并且允许将事件处理程序附加到原始控件以及公开冒泡的事件的控件上。 冒泡法的实现,使用Control基类中专门用于事件上传的两个方法:OnBubbleEvent和RaiseBubbleEvent。OnBubbleEvent方法用于确定子控件的事件是否沿复合控件层次结构向上传递。在该方法中,参数source表示事件源,参数args表示包含事件数据的EventArgs对象。如果子控件的事件向上传递,则为true;否则为false。默认值为false。RaiseBubbleEvent方法用于将所有事件源及其信息分配给控件的父级,并且不能被重写。尽管无法重写此方法,但创作的控件可以通过重写 OnBubbleEvent 方法处理或引发冒泡事件。 还是通过例子说明一下: 首先在CreateChildControls()中声明commandname属性。 _button.CommandName ="ClickLogin"; 然后定义事件: privatestaticreadonlyobject EventClickLogin =newobject();publicevent EventHandler ClickLogin{            add{                Events.AddHandler(EventClickLogin, value);            }            remove{                Events.RemoveHandler(EventClickLogin, value);            }        }protectedvirtualvoid OnClickLogin(EventArgs e){            EventHandler clickLoginHandler = (EventHandler)Events[EventClickLogin];if (clickLoginHandler !=null){                clickLoginHandler(this, e);            }        }protectedoverridebool OnBubbleEvent(object source, EventArgs e){bool handled =false;if (e is CommandEventArgs){                CommandEventArgs ce = (CommandEventArgs)e;if (ce.CommandName =="ClickLogin"){                    OnClickLogin(EventArgs.Empty);                    handled =true;                }            }return handled;        }publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件{            OnClickLogin(new EventArgs());        } 里主要要注意的是:OnBubbleEvent()的使用。通过CommandName的值,来相应的找到处理事件的控件。 测试一下: protectedvoid LoginControl1_ClickLogin1(object sender, EventArgs e){     Label1.Text ="sssssssssssssssqwwssss";} 单击按钮,将触发上面的事件。 小结:这样,复合控件的基本使用就介绍完了,不是很难。只要记住特定的一些东西,就可以很容易的创造出复合控件。值得大家注意的是复合控件中事件的两种处理方法。希望对新手有帮助。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/23/1507554.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(3)--事件和回传数据的处理

  前两篇介绍了服务器控件的基本显示,属性的设定,继承Webcontrol开发控件等内容,这篇介绍下定制服务器控件的事件的处理和回传数据的处理。 当ASP.NET页面处理回传到服务器端的表单时,两种信息会传递给页面中的控件: 回传事件,如Button一类控件触发的回传,会引发服务器端事件; 回传数据:是Web表单中包含的数据,该数据是在Web表单提交到服务器端时传递给如TextBox一类的控件。 处理回传数据 PostBack(回传):ASP.NET控件提交表单到服务器端,将信息从浏览器传递到服务器端的过程。 我们可能经常会在Page_Load事件中写这样的代码: protectedvoid Page_Load(object sender, EventArgs e)        {if (!IsPostBack)            {.            }        } 但是初学的时候我们很少回去问,为什么要写这段代码,只知道这么写就是对的。其实这就是数据回传的一个表现,通过该值指示该页是否正为响应客户端回发而加载。 ASP.ENT服务器控件处理回传数据,基本上完成以下两个工作: -->继承并实现IPostBackDataHandler接口的  -->实现RaisePostDataChangedEvent方法,处理回发数据 通过例子说明一下,这里创建一个自己的文本框:创建一个ASP.NET服务器控件项目(MyTextBox) Codenamespace NewTextBox{    [DefaultProperty("Text")]    [ToolboxData("<{0}:NewTextBox runat=server></{0}:NewTextBox>")]publicclass NewTextBox : WebControl, IPostBackDataHandler    {publicevent EventHandler TextChanged; publicstring ViewText//定义显示文字属性        {get            {if (ViewState["Text"].Equals(null))                {return String.Empty;                }else                {return ViewState["Text"].ToString();                }            }set            {                ViewState["Text"] = value;            }        } protectedoverride HtmlTextWriterTag TagKey//向页面中添加文本框        {get            {return HtmlTextWriterTag.Input;            }        } protectedoverridevoid AddAttributesToRender(HtmlTextWriter writer)        {            writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");            writer.AddAttribute(HtmlTextWriterAttribute.Value, ViewText);            writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); base.AddAttributesToRender(writer);        } publicbool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)//表单域的值和控件的ViewText(此示例中)属性的当前值不匹配,那么将新的值赋给ViewText属性,并且返回True。只有当LoadPostData返回True的时候,才会调用RaisePostDataChangedEvent方法。        {if (postCollection[postDataKey] != ViewText)            {                ViewText = postCollection[postDataKey];returntrue;            }returnfalse;        } publicvoid RaisePostDataChangedEvent()        {if (TextChanged !=null)                TextChanged(this, EventArgs.Empty);        }     }} 测试一下: protectedvoid Button1_Click(object sender, EventArgs e)        {            Label1.Text = NewTextBox1.ViewText;        } 只有当文本框中是文字发生变化是,才会引起数据的回发并从新获得数据。(控件拖到页面时,要给viewText赋值)   处理回发事件 ASP.NET服务器控件处理回发事件,基本上需要完成以下两个工作: -->继承并实现IPostBackEventHandler接口的  -->实现RaisePostBackEvent方法,处理回发事件 Button控件继承IPostBackEventHandler接口(所有的按钮控件,ImageButton,LinkButtton都继承了这个接口)。IPostBackEventHandler接口专门定义了处理回发事件的方法,如果自定义控件需要处理回发事件,你就需要继承IPostBackEventHandler接口。 通过例子说明一下,这里我们定制一个自己的按钮:创建一个ASP.NET服务器控件项目(MyButton) Codenamespace MyButton{    [DefaultProperty("Text")]    [ToolboxData("<{0}:MyButton runat=server></{0}:MyButton>")]publicclass MyButton : WebControl, IPostBackEventHandler    {privatestaticreadonlyobject ClickKey =newobject(); publicevent EventHandler Click //定义事件的委托        {            add            {                Events.AddHandler(ClickKey, value);            }            remove            {                Events.RemoveHandler(ClickKey, value);            }        } protectedvirtualvoid OnClick(EventArgs e)//定义单击事件的处理程序        {            EventHandler clickEventDelegate = (EventHandler)Events[ClickKey]; if (clickEventDelegate !=null)            {                clickEventDelegate(this, e);            }        } publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件        {            OnClick(new EventArgs());        } protectedoverridevoid RenderContents(HtmlTextWriter output)        {            output.Write("<INPUT TYPE=submit name="+this.UniqueID +" Value='这是自己定制的按钮!' />");        }    }} 测试一下: protectedvoid MyButton1_Click(object sender, EventArgs e)        {            Label1.Text ="Hello World!!!!!!!!!";        } 按钮的事件回发处理成功。 客户端回发事件 在asp.net2.0中,Button 控件多了一个UseSubmitBehavior 属性,指示 Button 控件使用客户端浏览器的提交机制(客户端回发)还是 ASP.NET 回发机制,默认采用ASP.NET回发机制,如果设置为false的话,则需要调用GetPostBackEventReference 方法来返回 Button 的客户端回发事件。 当设置UseSubmitBehavior 属性为flase时,运行页面时,则会发现一段自动生成的javascript代码(查看源文件) Code<script type="text/javascript">//<![CDATA[var theForm = document.forms['form1'];if (!theForm) {    theForm = document.form1;}function __doPostBack(eventTarget, eventArgument) {if (!theForm.onsubmit || (theForm.onsubmit() !=false)) {        theForm.__EVENTTARGET.value = eventTarget;        theForm.__EVENTARGUMENT.value = eventArgument;        theForm.submit();    }}//]]></script> 这里我们创建一个按钮,根据属性的设定,更改其事件回发的方式: Codenamespace MyLinkButton{    [DefaultProperty("Text")]    [ToolboxData("<{0}:MyLinkButton runat=server></{0}:MyLinkButton>")]publicclass MyLinkButton : WebControl, IPostBackEventHandler    {publicvirtual ButtonDisplay Display        {get            {object display = ViewState["Display"];if (display ==null)return ButtonDisplay.Button;elsereturn (ButtonDisplay)display;            }set            {                ViewState["Display"] = value;            }        } publicvirtualstring Text        {get            {object text = ViewState["Text"];if (text ==null)returnstring.Empty;elsereturn (string)text;            }set            {                ViewState["Text"] = value;            }        } privatestaticreadonlyobject ClickKey =newobject(); publicevent EventHandler Click//定义委托        {            add            {                Events.AddHandler(ClickKey, value);            }            remove            {                Events.RemoveHandler(ClickKey, value);            }        } protectedvirtualvoid OnClick(EventArgs e)//定义Click事件处理函数        {            EventHandler clickEventDelegate =               (EventHandler)Events[ClickKey];if (clickEventDelegate !=null)            {                clickEventDelegate(this, e);            }        } publicvoid RaisePostBackEvent(string argument)        {             OnClick(EventArgs.Empty);        } overrideprotectedvoid Render(HtmlTextWriter writer)        {base.Render(writer);            Page.VerifyRenderingInServerForm(this); if (Display == ButtonDisplay.Button)            {                writer.Write("<INPUT type=\"submit\"");                writer.Write(" name=\"" + this.UniqueID + "\"");                writer.Write(" id=\"" + this.UniqueID + "\"");                writer.Write(" value=\"" + Text + "\"");                writer.Write(" />");            }elseif (Display == ButtonDisplay.Hyperlink)            {                writer.Write("<A href=\"");                writer.Write(Page.ClientScript.GetPostBackClientHyperlink(this, ""));                writer.Write("\">" + Text + "</A>");            }        } publicenum ButtonDisplay        {            Button =0,            Hyperlink =1        }     } } 根据属性Display的属性的设置,对事件的回发进行控制,如果是Hyperlink则是客户端回发机制。   小结:新手在对事件的回发上可能会迷糊,但是不要紧,慢慢的理解。简单的理解事件的回发就是我们点击一个按钮发生的事件,而这个事件的处理ASP.NET给我们提供了两种方式。更多ASP.NET服务器控件事件可以参考: http://msdn.microsoft.com/zh-cn/library/cc437696(VS.71).aspx http://msdn.microsoft.com/zh-cn/library/xax2hw3x.aspx 写的不好,希望能对新手有帮助。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/19/1506243.html

龙生   08 Apr 2013
View Details
1 36 37 38 44