(转)ASP.NET自定义控件组件开发
|
ASP.NET自定义控件组件开发
(内容似乎不全,请找原版) 第一章:从一个简单的控件谈起 起始开发ASP.NET自定义控件不是那么的高深,当初我开始学的时候还有点恐惧,但是慢慢就好了。学习控件的开发技术,并不一定说以后要从事控件的开发,而是让我们深入的理解掌握ASP.NET内部的机理。你会发觉,当学习完控件开发技术后,你以后开发网站时有种得心应手的感觉。我不希望一上来就讲控件开始多么多么难啊,我会用一个演化的方法来讲述控件开发,一步一步帮助大家理解,如果大家要求的话,我会考虑录制视频讲解。当然,也很希望去webcast上讲讲这个系列。
代码也会附带的放上,希望大家支持!!! 现在开始:首先看一个简单的页面: 下面是个html的页面,显示的是一些html控件的页面。 ![]() 当我们查看页面后面的html代码时,就发现很复杂 ![]() 上面显示的是一个输入用户信息的提交控件,如果这个控件很常用,那么我们每次都要这样拖放,那是很累的,为了便于代码重用,就吧它实现为一个控件。 一般来说,自定义控件的都是继承于某一个基类的,不仅如此,我们所用的所有的控件都是继承于一个基类Control类。我们开发控件可以继承任何的服务器控件,如Button,TextBox等等。但是我们一般都继承于三个基类Control,WebControl,CompositeControl,因为这些类给了我们更加灵活的操作。 本章从浅入深,主要讲解继承Control类。 |
|
| |
TOP |
|
2# 大 中 小 发表于 2009-1-5 14:44 只看该作者
开发继承于Control类的控件很简单,只要重写Render方法就可以了:
![]() 其实我们做的事情很简单:只是把之前的html的代码做为字符串传入了write.Write()方法中而已。 当把所有的这些html代码写完之后,恭喜你,一个自定义的服务器控件就成功了!让后你就可以把它放 放入工具箱中,像其他的控件,如Button,TextBox,等一样的使用了。 下面来一步步的介绍得到一个控件: 1. 写完之前的代码后,然后生成: ![]() 这样,一个控件就生成了。 2. 我们新建一个测试的网站的 ![]() 3. 在工具箱中点击右键-“选择项“,弹出如下: 4. 点击“浏览“,然后找到我们存放项目的地方 ![]() 5. 然后就进入”CreditCardForm”—“obj—“Debug” |
|
| |
TOP |
|
3# 大 中 小 发表于 2009-1-5 14:44 只看该作者
你会看到一个.dll
![]() 6. 然后选中那个.dll就可以,然后添加 7. 然后就可以在工具箱中找到你的控件 ![]() 然后拖过来就可以使用了 好了,经过上面的步骤,你就已经开发了一个控件,很简单吧!以后你只要添加了这个控件的.dll,你就可以在任何程序和项目中使用他,但是这个控件只是个演示,离实用来有距离,不用怕,慢慢来。 今天先写到这里。 大家给点建议吧! 项目的完整代码已经写完了但是不知道怎样放上来 要代码的就说下 1 2 3usingSystem; 4usingSystem.Collections.Generic; 5usingSystem.Text; 6usingSystem.Web; 7usingSystem.Web.UI; 8usingSystem.Web.UI.WebControls; 9 10namespaceCreditCardForm 11{ 12 publicclassCreditCardForm1:Control 13 { 14 protectedoverridevoidRender(HtmlTextWriterwriter) 15 { 16 writer.Write("<tablestyle='width:287px;height:128px;border-width:0'>"); 17 writer.Write("<tr>"); 18 writer.Write("<td>支付方式</td>"); 19 writer.Write("<td>"); 20 writer.Write("<selectname='paymentMethod'id='paymentMethod'style='width:100%'>"); 21 writer.Write("<optionvalue='0'>Master</option>"); 22 writer.Write("<optionvalue='1'>Visa</option>"); 23 writer.Write("</select>"); 24 writer.Write("</td>"); 25 writer.Write("</tr>"); 26 27 writer.Write("<tr>"); 28 writer.Write("<td>信用卡号</td>"); 29 writer.Write("<td><inputtype='text'name='CreditCardNo'id='CreditCardNo'/></td>"); 30 writer.Write("</tr>"); 31 32 writer.Write("<tr>"); 33 writer.Write("<td>持卡人</td>"); 34 writer.Write("<td><inputtype='text'name='CardholderName'id='CardholderName'/></td>"); 35 writer.Write("</tr>"); 36 37 writer.Write("<tr>"); 38 writer.Write("<td>过期时间</td>"); 39 writer.Write("<td>"); 40 writer.Write("<selectname='Month'id='Month'>"); 41 for(intmonth=1;month<13;month++) 42 { 43 writer.Write("<opti>"+month.ToString()+"</option>"); 44 } 45 46 writer.Write("</select>"); 47 48 writer.Write(" "); 49 50 writer.Write("<selectname='Year'id='Year'>"); 51 for(intyear=2008;year<2014;year++) 52 { 53 writer.Write("<opti>"+year.ToString()+"</option>"); 54 } 55 writer.Write("</select>"); 56 writer.Write("</td></tr>"); 57 58 writer.Write("<tr>"); 59 writer.Write("<tdalign='center'colspan='2'>"); 60 writer.Write("<inputtype='submit'value='提交'/>"); 61 writer.Write("</td></tr>"); 62 63 64 65 66 } 67 68 } 69} 70 71 72 |
|
| |
TOP |
|
4# 大 中 小 发表于 2009-1-5 14:45 只看该作者
很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了一些例子,想选中一些好上手的例子,这样,可能一些例子大家以前都见过,但是我想说:同样是弹钢琴,同样一首“命运交响曲”,有的人弹的让人荡气回肠,有的人弹的就很一般。
受了李建忠老师的启发,发现用一种演化式的让人更好的接受。 好了,废话不说了。继续开发!希望大家支持! 我们之前开发了一个很简单的自定义的控件,方法很简单,只是把原来的html文本传入writer.Writer()方法的参数,然后输出。其实从模式的角度看,这可说是个Template模式(只是提下而已,有兴趣的朋友可以和我讨论)! 大家再来看看代码: usingSystem; usingSystem.Collections.Generic; usingSystem.Text; usingSystem.Web; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceCreditCardForm { publicclassCreditCardForm1:Control { protectedoverridevoidRender(HtmlTextWriterwriter) { writer.Write("<tablestyle='width:287px;height:128px;border-width:0'>"); writer.Write("<tr>"); writer.Write("<td>支付方式</td>"); writer.Write("<td>"); writer.Write("<selectname='paymentMethod'id='paymentMethod'style='width:100%'>"); writer.Write("<optionvalue='0'>Master</option>"); writer.Write("<optionvalue='1'>Visa</option>"); writer.Write("</select>"); writer.Write("</td>"); writer.Write("</tr>"); writer.Write("<tr>"); writer.Write("<td>信用卡号</td>"); writer.Write("<td><inputtype='text'name='CreditCardNo'id='CreditCardNo'/></td>"); writer.Write("</tr>"); writer.Write("<tr>"); writer.Write("<td>持卡人</td>"); writer.Write("<td><inputtype='text'name='CardholderName'id='CardholderName'/></td>"); writer.Write("</tr>"); writer.Write("<tr>"); writer.Write("<td>过期时间</td>"); writer.Write("<td>"); writer.Write("<selectname='Month'id='Month'>"); for(intmonth=1;month<13;month++) { writer.Write("<optionvalue="+month.ToString()+">"+month.ToString()+"</option>"); } writer.Write("</select>"); writer.Write(" "); writer.Write("<selectname='Year'id='Year'>"); for(intyear=2008;year<2014;year++) { writer.Write("<optionvalue="+year.ToString()+">"+year.ToString()+"</option>"); } writer.Write("</select>"); writer.Write("</td></tr>"); writer.Write("<tr>"); writer.Write("<tdalign='center'colspan='2'>"); writer.Write("<inputtype='submit'value='提交'/>"); writer.Write("</td></tr>"); } } } |
|
| |
TOP |
|
5# 大 中 小 发表于 2009-1-5 14:46 只看该作者
我们发现,这个控件实现的很僵硬!因为这个控件不像其他的服务器控件,我们这个控件没有任何让我们编辑的地方,也没有一些让我们设置的属性。下面,我们就来让控件“活”起来。给他一些可以编辑的属性。 首先我们还是从最简单来看。
相信大家都知道C#中的get ,set,我们总是把成为“属性”(Property),其实在控件开发的时候,就是用这些get, 和set来设置属性的。 先来看看这张图片: ![]() 大家都熟悉吧,就是我们之前前开发的那个控件的外观。我们在拖控件是使用的时候,一般都要设置一些属性,比如:Text,Name等等。当然,这里也不例外,我们也设置这个控件的属性,例如我们想让控件左边的文本改变,就像改变Text属性,如下: ![]() 这样的控件就更加的灵活。下面来看看这样开发这些属性吧! 用get和set 如下: 1 private string paymentMethod = "支付方式"; 2 private string creditCardNo = "信用卡号"; 3 private string cardholderName = "持卡人"; 4 private string expirati; 5 private string submitButt; 6 7 //以便以后二次开发 所以用了virtual 8 // 9 10 11 public virtual string PaymentMethodText 12 { 13 get 14 { 15 return paymentMethod; 16 } 17 set 18 { 19 paymentMethod = value; 20 } 21 } 22 23 public virtual string CreditCardNoText 24 { 25 get 26 { 27 return creditCardNo; 28 } 29 set 30 { 31 creditCardNo = value; 32 } 33 } 34 35 public virtual string CardholderNameText 36 { 37 get 38 { 39 return cardholderName; 40 } 41 set 42 { 43 cardholderName = value; 44 } 45 } 46 47 public virtual string ExpirationDateText 48 { 49 get 50 { 51 return expirationDate; 52 } 53 set 54 { 55 expirationDate = value; 56 } 57 } 58 59 public virtual string SubmitButtonText 60 { 61 get 62 { 63 return submitButtonText; 64 } 65 set 66 { 67 submitButtonText = value; 68 } 69 } |
|
| |
TOP |
|
6# 大 中 小 发表于 2009-1-5 14:51 只看该作者
这样做以后,基本上就完成了我们之前的目的,可以设置控件的属性了。注意:我们这里实现的属性是可读写的。大家可以根据情况来确定是只读,还是只写!
但是我们不要忘记了,控件的显示是通过Render方法呈现在页面的,我们要使得我们的控件可以改变属性,改变呈现的方式,就要改改Render中的代码:如下: 1protectedoverridevoidRender(HtmlTextWriterwriter) 2 { 3 writer.Write("<tablestyle='width:287px;height:128px;border-width:0'>"); 4 writer.Write("<tr>"); 5 writer.Write("<td>"+PaymentMethodText+"</td>"); 6 writer.Write("<td>"); 7 writer.Write("<selectname='paymentMethod'id='paymentMethod'style='width:100%'>"); 8 writer.Write("<optionvalue='0'>Master</option>"); 9 writer.Write("<optionvalue='1'>Visa</option>"); 10 writer.Write("</select>"); 11 writer.Write("</td>"); 12 writer.Write("</tr>"); 13 14 writer.Write("<tr>"); 15 writer.Write("<td>"+CreditCardNoText+"</td>"); 16 writer.Write("<td><inputtype='text'name='CreditCardNo'id='CreditCardNo'/></td>"); 17 writer.Write("</tr>"); 18 19 writer.Write("<tr>"); 20 writer.Write("<td>"+CardholderNameText+"</td>"); 21 writer.Write("<td><inputtype='text'name='CardholderName'id='CardholderName'/></td>"); 22 writer.Write("</tr>"); 23 24 writer.Write("<tr>"); 25 writer.Write("<td>"+ExpirationDateText+"</td>"); 26 writer.Write("<td>"); 27 writer.Write("<selectname='Month'id='Month'>"); 28 for(intmonth=1;month<13;month++) 29 { 30 writer.Write("<optionvalue="+month.ToString()+">"+month.ToString()+"</option>"); 31 } 32 33 writer.Write("</select>"); 34 35 writer.Write(" "); 36 37 writer.Write("<selectname='Year'id='Year'>"); 38 for(intyear=2008;year<2014;year++) 39 { 40 writer.Write("<optionvalue="+year.ToString()+">"+year.ToString()+"</option>"); 41 } 42 writer.Write("</select>"); 43 writer.Write("</td></tr>"); 44 45 writer.Write("<tr>"); 46 writer.Write("<tdalign='center'colspan='2'>"); 47 writer.Write("<inputtype='submit'value='"+SubmitButtonText+"'/>"); 48 writer.Write("</td></tr>"); 49 50 51 52 53 } |
|
| |
TOP |
|
7# 大 中 小 发表于 2009-1-5 14:51 只看该作者
这里,请大家注意代码的第5,15,20,25,和47行,我们之前在前一个控件中是直接写如字符串,这里我们改变了写法。用到了我们定义的那些get,set的属性,来改变控件显示。
好了,这写步骤完成之后,工作就差不多完成了。 我想大家应该来记得我们平时用的控件,如下: ![]() 例如上面的TextBox控件,他的属性就显示在属性窗口,而且属性都分了类,如”外观“,”行为“,而且没有属性下面都有注释。大家注意途中的标记部分。 我们上面的代码确实已经为控件添加了属性,但是我们要让我们开发的控件和现有的控件一样,看起来更加的专业,我们就要实现一些显示的代码,使得我们的控件和现有的服务器控件一样”好看,好用”。即,要有下面的效果: ![]() 这个控件看起来很专业吧!好了,我们来实现下: 其实很简单的,只要添加一些属性(Attribute)标记 [Browsable(true)]//在属性窗口中是否可见 [Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类 [DefaultValue("支付方式")] [Description("支付方式")]//这些是显示在属性窗口底下的 publicvirtualstringPaymentMethodText { get { returnpaymentMethod; } set { paymentMethod=value; } } |
|
| |
TOP |
|
8# 大 中 小 发表于 2009-1-5 14:51 只看该作者
大家可以根据我的注释再结合我上面的标记图可以看看。然后其他的的一些get,set属性都添加差不多,只是括号()内的文本,随你写而已!
到此为止,一个”好看“的控件就写完了。至于“好用”,暂时不急,慢慢来! 当我们把控件添加到页面后,查看他的“源”看到的这样的: <cc1:creditcardform1id="CreditCardForm1_1"runat="server"></cc1:creditcardform1> 我们看到其他的一些控件的“源”,例如: <asp:TextBoxID="TextBox1"runat="server"Font-Bold="True"Font-Italic="True"Height="200px"TextMode="MultiLine"></asp:TextBox> TextBox控件的很多的属性都显示在标记中了,我们也希望当我们的控件一拖上页面的时候就显示一些包含在标记中的属性,如下: <cc1:CreditCardForm2ID="CreditCardForm2_1"runat="server"PaymentMethodText=" 我的支付"CardholderNameText="持卡姓名"CreditCardNoText="我的卡号"ExpirationDateText="过期吗?"> </cc1:CreditCardForm2> 怎样做? 也很简单,加些Attribute标记就行了。 这些的标记是类级别的,就是说,要用在类上,我们之前家的那些标记都用在字段上,级别不同。注意哦! 如下: 1[ToolboxData("<{0}:CreditCardForm2runat='server'PaymentMethodText='支付方式'></{0}:CreditCardForm2>")] 2 publicclassCreditCardForm2:Control |
|
| |
TOP |
|
9# 大 中 小 发表于 2009-1-5 14:52 只看该作者
注意:在{0}的冒号中之后的那个"CreditCardForm2“就是类的名字,不要写错,否就不行!还有runat='sever'一定要写,其他的属性你可以随意加,但是要保证,那些你的家的属性是我们定义了的。例如你还可以加 CreditCardNo='信用卡号',等等。这样之后,我们的控件就更加的专业了!
整个代码如下:大家多多提意见,如果我讲不够好就说,我尽量讲的更加平实! 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4usingSystem.Web.UI; 5usingSystem.Web; 6usingSystem.ComponentModel; 7usingSystem.Web.UI.WebControls; 8 9namespaceCreditCardForm 10{ 11 [DefaultProperty("CardholderNameText")] 12 [ToolboxData("<{0}:CreditCardForm2runat='server'PaymentMethodText='支付方式'></{0}:CreditCardForm2>")] 13 publicclassCreditCardForm2:Control 14 { 15 #region属性 16 privatestringpaymentMethod="支付方式"; 17 privatestringcreditCardNo="信用卡号"; 18 privatestringcardholderName="持卡人"; 19 privatestringexpirati; 20 privatestringsubmitButt; 21 22 //以便以后二次开发所以用了virtual 23 // 24 25 26 [Browsable(true)]//在属性窗口中是否可见 27 [Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类 28 [DefaultValue("支付方式")] 29 [Description("支付方式")]//这些是显示在属性窗口底下的 30 publicvirtualstringPaymentMethodText 31 { 32 get 33 { 34 returnpaymentMethod; 35 } 36 set 37 { 38 paymentMethod=value; 39 } 40 } 41 42 [Browsable(true)] 43 [Category("Appearance")] 44 [DefaultValue("信用卡号")] 45 [Description("信用卡的号码")] 46 publicvirtualstringCreditCardNoText 47 { 48 get 49 { 50 returncreditCardNo; 51 } 52 set 53 { 54 creditCardNo=value; 55 } 56 } 57 58 [Browsable(true)] 59 [Category("Appearance")] 60 [DefaultValue("持卡人")] 61 [Description("持卡人的名字")] 62 publicvirtualstringCardholderNameText 63 { 64 get 65 { 66 returncardholderName; 67 } 68 set 69 { 70 cardholderName=value; 71 } 72 } 73 74 [Browsable(true)] 75 [Category("Appearance")] 76 [DefaultValue("过期时间")] 77 [Description("描述卡的过期时间")] 78 publicvirtualstringExpirationDateText 79 { 80 get 81 { 82 returnexpirationDate; 83 } 84 set 85 { 86 expirationDate=value; 87 } 88 } 89 [Browsable(true)] 90 [Description("按钮的文本")] 91 [Category("Appearance")] 92 [DefaultValue("提交")] 93 publicvirtualstringSubmitButtonText 94 { 95 get 96 { 97 returnsubmitButtonText; 98 } 99 set 100 { 101 submitButtonText=value; 102 } 103 } 104 #endregion 105 protectedoverridevoidRender(HtmlTextWriterwriter) 106 { 107 writer.Write("<tablestyle='width:287px;height:128px;border-width:0'>"); 108 writer.Write("<tr>"); 109 writer.Write("<td>"+PaymentMethodText+"</td>"); 110 writer.Write("<td>"); 111 writer.Write("<selectname='paymentMethod'id='paymentMethod'style='width:100%'>"); 112 writer.Write("<optionvalue='0'>Master</option>"); 113 writer.Write("<optionvalue='1'>Visa</option>"); 114 writer.Write("</select>"); 115 writer.Write("</td>"); 116 writer.Write("</tr>"); 117 118 writer.Write("<tr>"); 119 writer.Write("<td>"+CreditCardNoText+"</td>"); 120 writer.Write("<td><inputtype='text'name='CreditCardNo'id='CreditCardNo'/></td>"); 121 writer.Write("</tr>"); 122 123 writer.Write("<tr>"); 124 writer.Write("<td>"+CardholderNameText+"</td>"); 125 writer.Write("<td><inputtype='text'name='CardholderName'id='CardholderName'/></td>"); 126 writer.Write("</tr>"); 127 128 writer.Write("<tr>"); 129 writer.Write("<td>"+ExpirationDateText+"</td>"); 130 writer.Write("<td>"); 131 writer.Write("<selectname='Month'id='Month'>"); 132 for(intmonth=1;month<13;month++) 133 { 134 writer.Write("<opti>"+month.ToString()+"</option>"); 135 } 136 137 writer.Write("</select>"); 138 139 writer.Write(" "); 140 141 writer.Write("<selectname='Year'id='Year'>"); 142 for(intyear=2008;year<2014;year++) 143 { 144 writer.Write("<opti>"+year.ToString()+"</option>"); 145 } 146 writer.Write("</select>"); 147 writer.Write("</td></tr>"); 148 149 writer.Write("<tr>"); 150 writer.Write("<tdalign='center'colspan='2'>"); 151 writer.Write("<inputtype='submit'value='"+SubmitButtonText+"'/>"); 152 writer.Write("</td></tr>"); 153 154 155 156 157 } 158 159 } 160} 161 |
|
| |
TOP |
|
10# 大 中 小 发表于 2009-1-5 14:52 只看该作者
第三篇:第一章的完结篇
相信大家看了前几篇文章后应该觉得自定义控件很简单,无非就是把一大堆的html代码包装一下就行了。不错,前 几篇写的控件确实很简单。不知道大家想过没有,难道我们每次写控件都要大费力气的把一大堆的html代码写进去吗。 不知道大家试了没有:如果在write.Write()方法中写的html代码有了错误,如果把<table..>写成了<talbe..>,在编译 的时候,编译器是不会发现错误,但是当我们把控件拖上来使用的时候,就发现控件的呈现错误。就是说,这样的错误只能 到最后才能被我们发现,这样我们又得回去改代码,然后重新的编译,生成。 我们开发的那个控件真的很好的,我们也也许没有考虑到浏览器版本的问题,因为不同的浏览器对html的不同版本的显 示还是有区别的。看看我们的代码,我们就敢保证我们的控件在所有的浏览器上都显示的是我们想要的结果吗? 基于上述原因,我们对之前的控件再来一次修改。 在.NET中,我们写代码经常用到他的智能感应功能,比如我们写完后加个".",然后,后面的一些属性,方法都显示出来 了 。而且在编译的时候,也提示我们一些错误信息。 下面我们就来改下: 1 amespace CreditCardForm 2 { 3 public class CreditCardForm3:CreditCardForm2 4 { 因为我们之前开发的控件已经实现了很多的特性,我们不想再意义的重新实现,所以就继承前面已经有的控件,相信大家 都理解这点。 writer.Write("<table style='width:287px;height:128px;border-width:0'>"); 大家还记得这段代码吧,我们想显示一个table,而且确定他的一些属性等等。如前所说,出错的可能很大,而且兼容也 |
|
有问题。怎样改?
这样: 我们用.NET里面的专门用来生成这些html标记的一些方法和属性 1 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px"); 2 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px"); 3 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0"); 4 writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable"); 5 writer.RenderBeginTag(HtmlTextWriterTag.Table); 这段代码和上端代码的最终的显示结果都是一样的(都生成相同的html标记)。也许大家会认为这段代码很多,难道写 这么多的代码就是好的吗,还不如之前的方便。但是,想想之前所说的问题,这段代码就解决了那些问题。 代码我来解释下:用AddStyleAttribute方法来添加CCS样式;AddStyleAttribute添加非CSS样式,如name,id等, 用RenderBeginTag来添加开始的标记。还有一点就是这些代码都是“反的”:先定义样式,属性,最后才定义我们要写的 个table标记。就是说,想给某个标记加属性,要先写属性, 样式的语句,在写这个标记。 1 writer.RenderBeginTag(HtmlTextWriterTag.Table); 2 看看上面的代码,显示的是个table标记,如果想显示tr?这样做: 1 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 2 大家应该明白我的意思了吧:HtmlTextWriterTag接不同的属性,就显示不同的标记。 还有一点要特别的注意,有开始,就是结束。我们用了一个RenderBeginTag方法,就一定要有个RenderEndTag方法 |
|
| |
TOP |
|
12# 大 中 小 发表于 2009-1-5 14:53 只看该作者
与之对应。
看个例子: 1 writer.RenderBeginTag(HtmlTextWriterTag.Td); 2 writer.Write(PaymentMethodText); 3 writer.RenderEndTag(); 大家懂了吧! 我把代码贴上,大家看看,有问题就说! 1 protected override void Render(HtmlTextWriter writer) 2 { 3 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px"); 4 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px"); 5 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0"); 6 writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable"); 7 writer.RenderBeginTag(HtmlTextWriterTag.Table); 8 9 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 10 11 writer.RenderBeginTag(HtmlTextWriterTag.Td); 12 writer.Write(PaymentMethodText); 13 writer.RenderEndTag(); 14 15 writer.RenderBeginTag(HtmlTextWriterTag.Td); 16 writer.AddAttribute(HtmlTextWriterAttribute.Name, "PaymentMethod"); 17 writer.AddAttribute(HtmlTextWriterAttribute.Id, "PaymentMethod"); 18 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%"); 19 writer.RenderBeginTag(HtmlTextWriterTag.Select); 20 21 writer.AddAttribute(HtmlTextWriterAttribute.Value, "0"); 22 writer.RenderBeginTag(HtmlTextWriterTag.Option); 23 writer.Write("Master"); 24 writer.RenderEndTag(); 25 26 writer.AddAttribute(HtmlTextWriterAttribute.Value, "1"); 27 writer.RenderBeginTag(HtmlTextWriterTag.Option); 28 writer.Write("Visa"); 29 writer.RenderEndTag(); 30 31 writer.RenderEndTag(); 32 writer.RenderEndTag(); 33 writer.RenderEndTag(); 34 35 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 36 writer.RenderBeginTag(HtmlTextWriterTag.Td); 37 writer.Write(CreditCardNoText); 38 writer.RenderEndTag(); 39 40 writer.RenderBeginTag(HtmlTextWriterTag.Td); 41 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); 42 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo"); 43 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo"); 44 writer.RenderBeginTag(HtmlTextWriterTag.Input); 45 writer.RenderEndTag(); 46 writer.RenderEndTag(); 47 writer.RenderEndTag(); 48 49 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 50 writer.RenderBeginTag(HtmlTextWriterTag.Td); 51 writer.Write(CardholderNameText); 52 writer.RenderEndTag(); 53 54 writer.RenderBeginTag(HtmlTextWriterTag.Td); 55 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); 56 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CardholderName"); 57 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CardholderName"); 58 writer.RenderBeginTag(HtmlTextWriterTag.Input); 59 writer.RenderEndTag(); 60 writer.RenderEndTag(); 61 writer.RenderEndTag(); 62 63 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 64 writer.RenderBeginTag(HtmlTextWriterTag.Td); 65 writer.Write(ExpirationDateText); 66 writer.RenderEndTag(); 67 68 writer.RenderBeginTag(HtmlTextWriterTag.Td); 69 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Month"); 70 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Month"); 71 writer.RenderBeginTag(HtmlTextWriterTag.Select); 72 for (int month = 1; month < 13; month++) 73 { 74 writer.AddAttribute(HtmlTextWriterAttribute.Value, month.ToString()); 75 writer.RenderBeginTag(HtmlTextWriterTag.Option); 76 writer.Write(month.ToString()); 77 writer.RenderEndTag(); 78 } 79 80 writer.RenderEndTag(); 81 82 writer.Write(" "); 83 84 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Year"); 85 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Year"); 86 writer.RenderBeginTag(HtmlTextWriterTag.Select); 87 88 for (int year =2008; year < 2015; year++) 89 { 90 writer.AddAttribute(HtmlTextWriterAttribute.Value, year.ToString()); 91 writer.RenderBeginTag(HtmlTextWriterTag.Option); 92 writer.Write(year.ToString()); 93 writer.RenderEndTag(); 94 } 95 96 writer.RenderEndTag(); 97 98 writer.RenderEndTag(); 99 writer.RenderEndTag(); 100 101 102 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 103 writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); 104 writer.AddAttribute(HtmlTextWriterAttribute.Align, "center"); 105 writer.RenderBeginTag(HtmlTextWriterTag.Td); 106 writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit"); 107 writer.AddAttribute(HtmlTextWriterAttribute.Value, SubmitButtonText); 108 writer.RenderBeginTag(HtmlTextWriterTag.Input); 109 writer.RenderEndTag(); 110 writer.RenderEndTag(); 111 writer.RenderEndTag(); 112 113 //table的结束标记 114 writer.RenderEndTag(); 115 116 117 118 119 } |
|
| |
TOP |
|
13# 大 中 小 发表于 2009-1-5 14:53 只看该作者
下面开始说说。状态的管理,即ViewState; 之前的控件还有一个问题:
如下: ![]() 我们在页面后面写代码: 1protectedvoidPage_Load(objectsender,EventArgse) 2 { 3 if(!this.IsPostBack) 4 { 5 CreditCardForm2_1.PaymentMethodText="我的支付方式"; 6 CreditCardForm2_1.CardholderNameText="小洋"; 7 } 8 } 运行页面看见: ![]() 但是当你点击”提交“按钮,页面马上就变为了如下: ![]() 变回来了!!!!????? 这里就要讲讲ASP.NET的页面保存值的方式:因为现在的ASP.NET网站是基于http这种无状态协议的。大家应该都懂。 在ASP.NET的我们提交的一个页面,虽然看起来是一样的,但是他们本质上已经不是同一个页面了。而是我们现在看见的页 面获取了之前提交的那个页面的一些状态值。关于这点,到第四章详细讲述”页面的生命周期“中讲。 所有我们就要用个ViewState来保存页面回传的值。这里我不想讲很多的理论东西,大家先看看现在的问题怎样解决: |
|
| |
TOP |
|
14# 大 中 小 发表于 2009-1-5 14:54 只看该作者
public override string PaymentMethodText
{ get { return ViewState["PaymentMethodText"] != null ? (string)ViewState["PaymentMethodText"] : "支付方式"; } set { ViewState["PaymentMethodText"] = value; } } 因为我们继承于CreditCardForm2,大家看看我们在CreditCardForm2中写的: 1 2 [Browsable (true )]//在属性窗口中是否可见 3 [Category ("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类 4 [DefaultValue ("支付方式")] 5 [Description ("支付方式")]//这些是显示在属性窗口底下的 6 7 //virtual 方便以后二次开发 8 public virtual string PaymentMethodText 9 { 10 get 11 { 12 return paymentMethod; 13 } 14 set 15 { 16 paymentMethod = value; 17 } 18 } 19 注意:Virtual。 这样之后,我们的控件就完成了。完整的代码如下:希望大家支持! 1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Web; 5using System.Web.UI; 6using System.Web.UI.WebControls; 7 8namespace CreditCardForm 9{ 10 public class CreditCardForm3:CreditCardForm2 11 { 12 public override string PaymentMethodText 13 { 14 get 15 { 16 return ViewState["PaymentMethodText"] != null ? (string)ViewState["PaymentMethodText"] : "支付方式"; 17 } 18 set 19 { 20 ViewState["PaymentMethodText"] = value; 21 } 22 } 23 24 public override string CreditCardNoText 25 { 26 get 27 { 28 return ViewState["CreditCardNoText"] != null ? (string)ViewState["CreditCardNoText"] : "信用卡号"; 29 } 30 set 31 { 32 ViewState["CreditCardNoText"] = value; 33 } 34 } 35 36 public override string CardholderNameText 37 { 38 get 39 { 40 return ViewState["CardholderNameText"] != null ? (string)ViewState["CardholderNameText"] : "持卡人"; 41 } 42 set 43 { 44 ViewState["CardholderNameText"] = value; 45 } 46 } 47 48 public override string ExpirationDateText 49 { 50 get 51 { 52 return ViewState["ExpirationDateText"] != null ? (string)ViewState["ExpirationDateText"] : "过期时间"; 53 } 54 set 55 { 56 ViewState["ExpirationDateText"] = value; 57 } 58 } 59 60 public override string SubmitButtonText 61 { 62 get 63 { 64 return ViewState["SubmitButtonText"] != null ? (string)ViewState["SubmitButtonText"] : "提交"; 65 } 66 set 67 { 68 ViewState["SubmitButtonText"] = value; 69 } 70 } 71 protected override void Render(HtmlTextWriter writer) 72 { 73 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px"); 74 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px"); 75 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0"); 76 writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable"); 77 writer.RenderBeginTag(HtmlTextWriterTag.Table); 78 79 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 80 81 writer.RenderBeginTag(HtmlTextWriterTag.Td); 82 writer.Write(PaymentMethodText); 83 writer.RenderEndTag(); 84 85 writer.RenderBeginTag(HtmlTextWriterTag.Td); 86 writer.AddAttribute(HtmlTextWriterAttribute.Name, "PaymentMethod"); 87 writer.AddAttribute(HtmlTextWriterAttribute.Id, "PaymentMethod"); 88 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%"); 89 writer.RenderBeginTag(HtmlTextWriterTag.Select); 90 91 writer.AddAttribute(HtmlTextWriterAttribute.Value, "0"); 92 writer.RenderBeginTag(HtmlTextWriterTag.Option); 93 writer.Write("Master"); 94 writer.RenderEndTag(); 95 96 writer.AddAttribute(HtmlTextWriterAttribute.Value, "1"); 97 writer.RenderBeginTag(HtmlTextWriterTag.Option); 98 writer.Write("Visa"); 99 writer.RenderEndTag(); 100 101 writer.RenderEndTag(); 102 writer.RenderEndTag(); 103 writer.RenderEndTag(); 104 105 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 106 writer.RenderBeginTag(HtmlTextWriterTag.Td); 107 writer.Write(CreditCardNoText); 108 writer.RenderEndTag(); 109 110 writer.RenderBeginTag(HtmlTextWriterTag.Td); 111 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); 112 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo"); 113 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo"); 114 writer.RenderBeginTag(HtmlTextWriterTag.Input); 115 writer.RenderEndTag(); 116 writer.RenderEndTag(); 117 writer.RenderEndTag(); 118 119 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 120 writer.RenderBeginTag(HtmlTextWriterTag.Td); 121 writer.Write(CardholderNameText); 122 writer.RenderEndTag(); 123 124 writer.RenderBeginTag(HtmlTextWriterTag.Td); 125 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); 126 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CardholderName"); 127 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CardholderName"); 128 writer.RenderBeginTag(HtmlTextWriterTag.Input); 129 writer.RenderEndTag(); 130 writer.RenderEndTag(); 131 writer.RenderEndTag(); 132 133 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 134 writer.RenderBeginTag(HtmlTextWriterTag.Td); 135 writer.Write(ExpirationDateText); 136 writer.RenderEndTag(); 137 138 writer.RenderBeginTag(HtmlTextWriterTag.Td); 139 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Month"); 140 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Month"); 141 writer.RenderBeginTag(HtmlTextWriterTag.Select); 142 for (int month = 1; month < 13; month++) 143 { 144 writer.AddAttribute(HtmlTextWriterAttribute.Value, month.ToString()); 145 writer.RenderBeginTag(HtmlTextWriterTag.Option); 146 writer.Write(month.ToString()); 147 writer.RenderEndTag(); 148 } 149 150 writer.RenderEndTag(); 151 152 writer.Write(" "); 153 154 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Year"); 155 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Year"); 156 writer.RenderBeginTag(HtmlTextWriterTag.Select); 157 158 for (int year =2008; year < 2015; year++) 159 { 160 writer.AddAttribute(HtmlTextWriterAttribute.Value, year.ToString()); 161 writer.RenderBeginTag(HtmlTextWriterTag.Option); 162 writer.Write(year.ToString()); 163 writer.RenderEndTag(); 164 } 165 166 writer.RenderEndTag(); 167 168 writer.RenderEndTag(); 169 writer.RenderEndTag(); 170 171 172 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 173 writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2"); 174 writer.AddAttribute(HtmlTextWriterAttribute.Align, "center"); 175 writer.RenderBeginTag(HtmlTextWriterTag.Td); 176 writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit"); 177 writer.AddAttribute(HtmlTextWriterAttribute.Value, SubmitButtonText); 178 writer.RenderBeginTag(HtmlTextWriterTag.Input); 179 writer.RenderEndTag(); 180 writer.RenderEndTag(); 181 writer.RenderEndTag(); 182 183 writer.RenderEndTag(); 184 185 186 187 188 } 189 } 190} 191 |
|
| |
TOP |
|
15# 大 中 小 发表于 2009-1-5 15:00 只看该作者
第二章 继承WebControl的自定义控件 到现在为止,我已经写了三篇关于自定义控件开发的文章,很感谢大家的支持!不知道大家对我讲的方式有什么好的建议,我尽量使自定义控件的技术让更多的程序员同胞接受。好了,开发开始了!
本章还是延续上章的例子,开发一个CreditCardForm控件。 其实本章也不难,相信大家看完后,也觉得很简单! 我们首先开谈谈继承Control和WebControl的区别:其实二者最大的区别就是在,如果我们开发的控件继承WebControl,那么我们的控件就支持更多的CSS样式。而继承于Control的自定义控件的样式相对就少些。 其实还有一个区别就在开发的规范上。我们来简单的看看上一章的自定义控件的代码,主要来看看Render方法中的代码:大家只扫一眼就可以了。 1protectedoverridevoidRender(HtmlTextWriterwriter) 2 { 3 //显示table标记 4 writer.AddStyleAttribute(HtmlTextWriterStyle.Width,"287px"); 5 writer.AddStyleAttribute(HtmlTextWriterStyle.Height,"128px"); 6 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth,"0"); 7 writer.AddAttribute(HtmlTextWriterAttribute.Id,"mytable"); 8 writer.RenderBeginTag(HtmlTextWriterTag.Table); 9 10 //显示table类的标记包含tr,td还有一些textbox,下拉框等 11 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 12 13 writer.RenderBeginTag(HtmlTextWriterTag.Td); 14 writer.Write(PaymentMethodText); 15 writer.RenderEndTag(); 16 17 writer.RenderBeginTag(HtmlTextWriterTag.Td); 18 writer.AddAttribute(HtmlTextWriterAttribute.Name,"PaymentMethod"); 19 writer.AddAttribute(HtmlTextWriterAttribute.Id,"PaymentMethod"); 20 writer.AddStyleAttribute(HtmlTextWriterStyle.Width,"100%"); 21 writer.RenderBeginTag(HtmlTextWriterTag.Select); 22 23 writer.AddAttribute(HtmlTextWriterAttribute.Value,"0"); 24 writer.RenderBeginTag(HtmlTextWriterTag.Option); 25 writer.Write("Master"); 26 writer.RenderEndTag(); 27 28 writer.AddAttribute(HtmlTextWriterAttribute.Value,"1"); 29 writer.RenderBeginTag(HtmlTextWriterTag.Option); 30 writer.Write("Visa"); 31 writer.RenderEndTag(); 32 33 writer.RenderEndTag(); 34 writer.RenderEndTag(); 35 writer.RenderEndTag(); 36 37 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 38 writer.RenderBeginTag(HtmlTextWriterTag.Td); 39 writer.Write(CreditCardNoText); 40 writer.RenderEndTag(); 41 42 writer.RenderBeginTag(HtmlTextWriterTag.Td); 43 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 44 writer.AddAttribute(HtmlTextWriterAttribute.Name,"CreditCardNo"); 45 writer.AddAttribute(HtmlTextWriterAttribute.Id,"CreditCardNo"); 46 writer.RenderBeginTag(HtmlTextWriterTag.Input); 47 writer.RenderEndTag(); 48 writer.RenderEndTag(); 49 writer.RenderEndTag(); 50 51 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 52 writer.RenderBeginTag(HtmlTextWriterTag.Td); 53 writer.Write(CardholderNameText); 54 writer.RenderEndTag(); 55 56 writer.RenderBeginTag(HtmlTextWriterTag.Td); 57 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 58 writer.AddAttribute(HtmlTextWriterAttribute.Name,"CardholderName"); 59 writer.AddAttribute(HtmlTextWriterAttribute.Id,"CardholderName"); 60 writer.RenderBeginTag(HtmlTextWriterTag.Input); 61 writer.RenderEndTag(); 62 writer.RenderEndTag(); 63 writer.RenderEndTag(); 64 65 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 66 writer.RenderBeginTag(HtmlTextWriterTag.Td); 67 writer.Write(ExpirationDateText); 68 writer.RenderEndTag(); 69 70 writer.RenderBeginTag(HtmlTextWriterTag.Td); 71 writer.AddAttribute(HtmlTextWriterAttribute.Name,"Month"); 72 writer.AddAttribute(HtmlTextWriterAttribute.Id,"Month"); 73 writer.RenderBeginTag(HtmlTextWriterTag.Select); 74 for(intmonth=1;month<13;month++) 75 { 76 writer.AddAttribute(HtmlTextWriterAttribute.Value,month.ToString()); 77 writer.RenderBeginTag(HtmlTextWriterTag.Option); 78 writer.Write(month.ToString()); 79 writer.RenderEndTag(); 80 } 81 82 writer.RenderEndTag(); 83 84 writer.Write(" "); 85 86 writer.AddAttribute(HtmlTextWriterAttribute.Name,"Year"); 87 writer.AddAttribute(HtmlTextWriterAttribute.Id,"Year"); 88 writer.RenderBeginTag(HtmlTextWriterTag.Select); 89 90 for(intyear=2008;year<2015;year++) 91 { 92 writer.AddAttribute(HtmlTextWriterAttribute.Value,year.ToString()); 93 writer.RenderBeginTag(HtmlTextWriterTag.Option); 94 writer.Write(year.ToString()); 95 writer.RenderEndTag(); 96 } 97 98 writer.RenderEndTag(); 99 100 writer.RenderEndTag(); 101 writer.RenderEndTag(); 102 103 104 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 105 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 106 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 107 writer.RenderBeginTag(HtmlTextWriterTag.Td); 108 writer.AddAttribute(HtmlTextWriterAttribute.Type,"submit"); 109 writer.AddAttribute(HtmlTextWriterAttribute.Value,SubmitButtonText); 110 writer.RenderBeginTag(HtmlTextWriterTag.Input); 111 writer.RenderEndTag(); 112 writer.RenderEndTag(); 113 writer.RenderEndTag(); 114 115 //table的结束标记 116 writer.RenderEndTag(); 117 118 119 120 121 } |
|
| |
TOP |
|
16# 大 中 小 发表于 2009-1-5 15:00 只看该作者
相信这段代码大家都和熟悉。在这段代码的作用主要显示了一个table 以及table 之中的标记元素。
如果一这个控件已经写好了,加入我们想要改改table的样式,如把border设为1,或者改变显示的颜色等,那么我们就 要再次打开这段代码,修改代码。其实这就不好。为什么? 其实这个方法中的代码做了四件事: 1.显示控件最外层的包含标记,即table 2.显示最外层标记的一些属性,如border.id等 3.显示控件的主要内容 ,如,显示输入框,下拉框,按钮。 4.显示控件最外层包含标记的结束标记。 这样看来,这个方法的职责就有四个。大家应该还记得面向对象设计的原创:单一职责。虽然这个元素一般用在类上, 但是我们更加要注意,这个原则用的宗旨:使对象只有一个变化的因素。这个原则也用在方法的设计上。 就是说,我们如果想要改变最外层标记table一些属性,我们就影响了其他三个职责。同理,我们想改变其他的元素或者 内容,结果可想而知。 为此,继承WebControl的控件就更加的规范和灵活: 其实,继承于WebControl的控件的显示还是在Render方法中显示,只是这个Render方法已经不由我们来写了: 如下: 1 2 protectedoverridevoidRender(HtmlTextWriterwriter) 3 { 4 RenderBeginTag(writer); 5 RenderContens(writer); 6 RenderEndTag(writer); 7 8 } 因为我们之前说,Render方法的职责有四个。所以WebControl的Render方法就把这些职责分离了。以后我们能就 可以独立的改变一个因素了。大家也许奇怪:不是说有四个职责吗,但是上面只是显示了三个方法,其实在 |
|
| |
TOP |
|
17# 大 中 小 发表于 2009-1-5 15:01 只看该作者
RenderBeginTag()方法中包含显示最外层标记样式的方法。 所以我们只要分别重写这三个方法,一个继承WebControl的自定义的控件就成了。不要怕,方法很多,但是很简单,而
且代码我们都懂,之前差不多都讲了的。 我想把写成后的控件给大家看看,让大家看下我们本章的目标: ![]() 大家看见没有:是不是支持的样式多了!!! 好了,我们来写吧:不难哦:) 首先看看我们要的写方法以及他们的功能: protectedoverridevoidRender(HtmlTextWriterwriter) { //显示最外层包含标记开始的标记,即,显示<table..> RenderBeginTag(writer); //显示table标记内的内容,如<tr><td><input/>等 RenderContens(writer); //显示最外层包含标记结束标记</table RenderEndTag(writer); } 现在的思路很清晰吧,首先来显示<table....> 很简单,只要如下就可以了。 1 protectedoverrideHtmlTextWriterTagTagKey 2 { 3 get 4 { 5 returnHtmlTextWriterTag.Table; 6 } 7 } 不要奇怪,因为RenderBeginTag()方法内部实际是调用了这个属性来显示的最外层的包含标记的。 好了,第一步就写完了啊!简答吧! 下面来显示table的样式,因为我们的控件的最外层的标记是table,显示他的样式只要这样就OK了。 1 protectedoverrideStyleCreateControlStyle() 2 { 3 returnnewTableStyle(ViewState); 4 } 又写完了一部分。。不难吧!接着看啊! 如果你的最外层的标记是<div >那么,上面的那个方法你都不用写. |
|
| |
TOP |
|
18# 大 中 小 发表于 2009-1-5 15:01 只看该作者
下面就写了RenderContent方法,不难,只记住这个方法的职责:显示最外层标记的内容: 如下:
1protectedoverridevoidRenderContents(HtmlTextWriterwriter) 2 { 3 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 4 writer.RenderBeginTag(HtmlTextWriterTag.Td); 5 writer.Write(PaymentMethod); 6 writer.RenderEndTag(); 7 8 writer.RenderBeginTag(HtmlTextWriterTag.Td); 9 10 writer.AddAttribute(HtmlTextWriterAttribute.Id,PaymentMethodListId); 11 writer.AddAttribute(HtmlTextWriterAttribute.Name,PaymentMethodListName); 12 writer.AddStyleAttribute(HtmlTextWriterStyle.Width,"100%"); 13 writer.RenderBeginTag(HtmlTextWriterTag.Select); 14 15 writer.AddAttribute(HtmlTextWriterAttribute.Value,"0"); 16 writer.RenderBeginTag(HtmlTextWriterTag.Option); 17 writer.Write("Master"); 18 writer.RenderEndTag(); 19 20 writer.AddAttribute(HtmlTextWriterAttribute.Value,"1"); 21 writer.RenderBeginTag(HtmlTextWriterTag.Option); 22 writer.Write("Visa"); 23 writer.RenderEndTag(); 24 25 writer.RenderEndTag(); 26 27 writer.RenderEndTag(); 28 writer.RenderEndTag(); 29//**************************************************************************** 30 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 31 writer.RenderBeginTag(HtmlTextWriterTag.Td); 32 writer.Write(CreditCardNo); 33 writer.RenderEndTag(); 34 35 writer.RenderBeginTag(HtmlTextWriterTag.Td); 36 writer.AddAttribute(HtmlTextWriterAttribute.Id,CreditCardNoTextId); 37 writer.AddAttribute(HtmlTextWriterAttribute.Name,CreditCardNoTextName); 38 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 39 writer.RenderBeginTag(HtmlTextWriterTag.Input); 40 writer.RenderEndTag(); 41 42 writer.RenderEndTag(); 43 writer.RenderEndTag(); 44//************************************************************************************** 45 46 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 47 writer.RenderBeginTag(HtmlTextWriterTag.Td); 48 writer.Write(CardholderName); 49 writer.RenderEndTag(); 50 51 writer.RenderBeginTag(HtmlTextWriterTag.Td); 52 writer.AddAttribute(HtmlTextWriterAttribute.Name,CardholderNameTextName); 53 writer.AddAttribute(HtmlTextWriterAttribute.Id,CardholderNameTextId); 54 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 55 writer.RenderBeginTag(HtmlTextWriterTag.Input); 56 writer.RenderEndTag(); 57 58 writer.RenderEndTag(); 59 writer.RenderEndTag(); 60//*************************************************************************************** 61 62 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 63 writer.RenderBeginTag(HtmlTextWriterTag.Td); 64 writer.Write(ExpirationDate); 65 writer.RenderEndTag(); 66 67 writer.RenderBeginTag(HtmlTextWriterTag.Td); 68 writer.AddAttribute(HtmlTextWriterAttribute.Name,MonthListName); 69 writer.AddAttribute(HtmlTextWriterAttribute.Id,MonthListId); 70 writer.RenderBeginTag(HtmlTextWriterTag.Select); 71 72 for(intmonth=1;month<13;month++) 73 { 74 writer.AddAttribute(HtmlTextWriterAttribute.Value,month.ToString()); 75 writer.RenderBeginTag(HtmlTextWriterTag.Option); 76 writer.Write(month.ToString()); 77 writer.RenderEndTag(); 78 } 79 writer.RenderEndTag(); 80 81 ///////////////////////////////////// 82 83 writer.Write(" "); 84 85 ///////////////////////////////////// 86 writer.AddAttribute(HtmlTextWriterAttribute.Name,YearListName); 87 writer.AddAttribute(HtmlTextWriterAttribute.Id,YearListId); 88 writer.RenderBeginTag(HtmlTextWriterTag.Select); 89 90 for(intyear=2008;year<2015;year++) 91 { 92 writer.AddAttribute(HtmlTextWriterAttribute.Value,year.ToString()); 93 writer.RenderBeginTag(HtmlTextWriterTag.Option); 94 writer.Write(year.ToString()); 95 writer.RenderEndTag(); 96 } 97 writer.RenderEndTag(); 98 99 writer.RenderEndTag(); 100 writer.RenderEndTag(); 101//***************************************************************************** 102 103 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 104 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 105 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 106 writer.RenderBeginTag(HtmlTextWriterTag.Td); 107 writer.AddAttribute(HtmlTextWriterAttribute.Name,SubmitButtonName); 108 writer.AddAttribute(HtmlTextWriterAttribute.Value,SubmitButtonText); 109 writer.AddAttribute(HtmlTextWriterAttribute.Id,SubmitButtonId); 110 writer.AddAttribute(HtmlTextWriterAttribute.Type,"submit"); 111 writer.RenderBeginTag(HtmlTextWriterTag.Input); 112 writer.RenderEndTag(); 113 114 writer.RenderEndTag(); 115 writer.RenderEndTag(); 116 117//****************************************************************************** 118 119 120 } |
|
| |
TOP |
|
19# 大 中 小 发表于 2009-1-5 15:01 只看该作者
这样就完了,大家看看上面的代码,很熟悉吧,是啊,只是把我们之前的代码分割开了,写在不同的地方!
最后的那个RendEndTag(),你不写!因为,你override那个TagKey时,就已经调用了结束标记的方法。这样,一个继承WebControl的控件就完了! 好了,写完了:完整的代码如下: 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4usingSystem.Web; 5usingSystem.Web.UI; 6usingSystem.Web.UI.WebControls; 7 8namespaceCreditCardForm 9{ 10 publicclassCreditCardForm5:WebControl 11 { 12 #region重写包含标记 13 14 protectedoverrideStyleCreateControlStyle() 15 { 16 returnnewTableStyle(ViewState); 17 } 18 19 protectedoverrideHtmlTextWriterTagTagKey 20 { 21 get 22 { 23 returnHtmlTextWriterTag.Table; 24 } 25 } 26 27 //publicvirtualstringBackImageUrl 28 //{ 29 // get 30 // { 31 // return((TableStyle)ControlStyle).BackImageUrl; 32 // } 33 // set 34 // { 35 // ((TableStyle)ControlStyle).BackImageUrl=value; 36 // } 37 //} 38 39 40 #endregion 41 #regionID 42 protectedvirtualstringPaymentMethodListId 43 { 44 get 45 { 46 return"PaymentMethod"; 47 } 48 } 49 50 protectedvirtualstringCreditCardNoTextId 51 { 52 get 53 { 54 return"CreditCardNo"; 55 } 56 } 57 58 protectedvirtualstringCardholderNameTextId 59 { 60 get 61 { 62 return"CardholderName"; 63 } 64 } 65 66 protectedvirtualstringMonthListId 67 { 68 get 69 { 70 return"Month"; 71 } 72 } 73 74 protectedvirtualstringYearListId 75 { 76 get 77 { 78 return "Year"; 79 } 80 } 81 82 protectedvirtualstringSubmitButtonId 83 { 84 get 85 { 86 return"Submit"; 87 } 88 } 89 90 #endregion 91 #regionname 92 protectedvirtualstringPaymentMethodListName 93 { 94 get 95 { 96 return"PaymentMethod"; 97 } 98 } 99 100 protectedvirtualstringCreditCardNoTextName 101 { 102 get 103 { 104 return"CreditCardNo"; 105 } 106 } 107 108 protectedvirtualstringCardholderNameTextName 109 { 110 get 111 { 112 return"CardholderName"; 113 } 114 } 115 116 protectedvirtualstringMonthListName 117 { 118 get 119 { 120 return"Month"; 121 } 122 } 123 124 protectedvirtualstringYearListName 125 { 126 get 127 { 128 return"Year"; 129 } 130 } 131 132 protectedvirtualstringSubmitButtonName 133 { 134 get 135 { 136 return"Sumit"; 137 } 138 } 139 #endregion 140 141 #region 属性 142 publicvirtualstringPaymentMethod 143 { 144 get 145 { 146 returnViewState["PaymentMethod"]!=null?(string)ViewState["PaymentMethod"]:"支付方式"; 147 148 } 149 set 150 { 151 ViewState["PaymentMethod"]=value; 152 } 153 } 154 155 publicvirtualstringCreditCardNo 156 { 157 get 158 { 159 returnViewState["CreditCardNo"]!=null?(string)ViewState["CreditCardNo"]:"信用卡号"; 160 } 161 set 162 { 163 ViewState["CreditCardNo"]=value; 164 } 165 } 166 167 publicvirtualstringCardholderName 168 { 169 get 170 { 171 returnViewState["CardholderName"]!=null?(string)ViewState["CardholderName"]:"持卡人"; 172 } 173 set 174 { 175 ViewState["CreditCardName"]=value; 176 } 177 } 178 179 publicvirtualstringExpirationDate 180 { 181 get 182 { 183 returnViewState["ExpirationDate"]!=null?(string)ViewState["ExpirationDate"]:"过期时间"; 184 } 185 set 186 { 187 ViewState["ExpirationDate"]=value; 188 } 189 } 190 191 publicvirtualstringSubmitButtonText 192 { 193 get 194 { 195 returnViewState["SubmitButtonText"]!=null?(string)ViewState["SubmitButtonText"]:"提交"; 196 } 197 set 198 { 199 ViewState["SubmitButtonText"]=value; 200 } 201 202 } 203 #endregion 204 protectedoverridevoidRenderContents(HtmlTextWriterwriter) 205 { 206 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 207 writer.RenderBeginTag(HtmlTextWriterTag.Td); 208 writer.Write(PaymentMethod); 209 writer.RenderEndTag(); 210 211 writer.RenderBeginTag(HtmlTextWriterTag.Td); 212 213 writer.AddAttribute(HtmlTextWriterAttribute.Id,PaymentMethodListId); 214 writer.AddAttribute(HtmlTextWriterAttribute.Name,PaymentMethodListName); 215 writer.AddStyleAttribute(HtmlTextWriterStyle.Width,"100%"); 216 writer.RenderBeginTag(HtmlTextWriterTag.Select); 217 218 writer.AddAttribute(HtmlTextWriterAttribute.Value,"0"); 219 writer.RenderBeginTag(HtmlTextWriterTag.Option); 220 writer.Write("Master"); 221 writer.RenderEndTag(); 222 223 writer.AddAttribute(HtmlTextWriterAttribute.Value,"1"); 224 writer.RenderBeginTag(HtmlTextWriterTag.Option); 225 writer.Write("Visa"); 226 writer.RenderEndTag(); 227 228 writer.RenderEndTag(); 229 230 writer.RenderEndTag(); 231 writer.RenderEndTag(); 232//**************************************************************************** 233 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 234 writer.RenderBeginTag(HtmlTextWriterTag.Td); 235 writer.Write(CreditCardNo); 236 writer.RenderEndTag(); 237 238 writer.RenderBeginTag(HtmlTextWriterTag.Td); 239 writer.AddAttribute(HtmlTextWriterAttribute.Id,CreditCardNoTextId); 240 writer.AddAttribute(HtmlTextWriterAttribute.Name,CreditCardNoTextName); 241 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 242 writer.RenderBeginTag(HtmlTextWriterTag.Input); 243 writer.RenderEndTag(); 244 245 writer.RenderEndTag(); 246 writer.RenderEndTag(); 247//************************************************************************************** 248 249 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 250 writer.RenderBeginTag(HtmlTextWriterTag.Td); 251 writer.Write(CardholderName); 252 writer.RenderEndTag(); 253 254 writer.RenderBeginTag(HtmlTextWriterTag.Td); 255 writer.AddAttribute(HtmlTextWriterAttribute.Name,CardholderNameTextName); 256 writer.AddAttribute(HtmlTextWriterAttribute.Id,CardholderNameTextId); 257 writer.AddAttribute(HtmlTextWriterAttribute.Type,"text"); 258 writer.RenderBeginTag(HtmlTextWriterTag.Input); 259 writer.RenderEndTag(); 260 261 writer.RenderEndTag(); 262 writer.RenderEndTag(); 263//*************************************************************************************** 264 265 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 266 writer.RenderBeginTag(HtmlTextWriterTag.Td); 267 writer.Write(ExpirationDate); 268 writer.RenderEndTag(); 269 270 writer.RenderBeginTag(HtmlTextWriterTag.Td); 271 writer.AddAttribute(HtmlTextWriterAttribute.Name,MonthListName); 272 writer.AddAttribute(HtmlTextWriterAttribute.Id,MonthListId); 273 writer.RenderBeginTag(HtmlTextWriterTag.Select); 274 275 for(intmonth=1;month<13;month++) 276 { 277 writer.AddAttribute(HtmlTextWriterAttribute.Value,month.ToString()); 278 writer.RenderBeginTag(HtmlTextWriterTag.Option); 279 writer.Write(month.ToString()); 280 writer.RenderEndTag(); 281 } 282 writer.RenderEndTag(); 283 284 ///////////////////////////////////// 285 286 writer.Write(" "); 287 288 ///////////////////////////////////// 289 writer.AddAttribute(HtmlTextWriterAttribute.Name,YearListName); 290 writer.AddAttribute(HtmlTextWriterAttribute.Id,YearListId); 291 writer.RenderBeginTag(HtmlTextWriterTag.Select); 292 293 for(intyear=2008;year<2015;year++) 294 { 295 writer.AddAttribute(HtmlTextWriterAttribute.Value,year.ToString()); 296 writer.RenderBeginTag(HtmlTextWriterTag.Option); 297 writer.Write(year.ToString()); 298 writer.RenderEndTag(); 299 } 300 writer.RenderEndTag(); 301 302 writer.RenderEndTag(); 303 writer.RenderEndTag(); 304//***************************************************************************** 305 306 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 307 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 308 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 309 writer.RenderBeginTag(HtmlTextWriterTag.Td); 310 writer.AddAttribute(HtmlTextWriterAttribute.Name,SubmitButtonName); 311 writer.AddAttribute(HtmlTextWriterAttribute.Value,SubmitButtonText); 312 writer.AddAttribute(HtmlTextWriterAttribute.Id,SubmitButtonId); 313 writer.AddAttribute(HtmlTextWriterAttribute.Type,"submit"); 314 writer.RenderBeginTag(HtmlTextWriterTag.Input); 315 writer.RenderEndTag(); 316 317 writer.RenderEndTag(); 318 writer.RenderEndTag(); 319 320//****************************************************************************** 321 322 323 } 324 325 } 326} 327 希望大家继续支持啊!谢谢! |
|
| |
TOP |
|
20# 大 中 小 发表于 2009-1-5 15:02 只看该作者
第三章 为控件添加事件 好了,我们之前以前开发一个控件。而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件。
ASP.NET的开发都是事件驱动的,现在我们就来为控件添加事件。在说事件之前,希望大家对C#的语法要熟悉,对委托很事件要懂。 其实定义事件的步骤很简单: 1.声明一个委托。 2.定义一个携带事件信息的类。 3.定义事件4.定义一个通事件发生后,通知其他对象的方法首先来理清一下我们的思路: 1.在下拉框中选中一个值,并且在输入框中也输入相应的值。 2.我们在页面点击“提交”按钮,按钮就触发我们自定义的一个事件Validate(验证输入信息的正确行)。 我们在提交的时候要把控件的信息传给服务器,所以我们要定义一个事件信息类,来携带事件发生时,把个信息类送到服务器。 事件定义如下: 1.定义一个携带事件信息的类。 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4 5namespaceCreditCardForm 6{ 7 publicclassValidateCreditCardFormEventArgs:EventArgs 8 { 9 privatestringpaymentMethod; 10 publicstringPaymentMethod 11 { 12 get 13 { 14 returnthis.paymentMethod; 15 } 16 } 17 18 19 privatestringcreditCardNo; 20 publicstringCreditCardNo 21 { 22 get 23 { 24 returnthis.creditCardNo; 25 } 26 } 27 28 29 privatestringcardholderName; 30 publicstringCardholderName 31 { 32 get 33 { 34 returnthis.cardholderName; 35 } 36 } 37 38 privateDateTimeexpirationDate; 39 publicDateTimeExpirationDate 40 { 41 get 42 { 43 returnthis.expirationDate; 44 } 45 } 46 47 48 publicValidateCreditCardFormEventArgs(stringpaymentmenthod,stringcreditcardno, 49 stringcardholdername,DateTimeexpirationdate) 50 { 51 this.paymentMethod=paymentmenthod; 52 this.creditCardNo=creditcardno; 53 this.cardholderName=cardholdername; 54 this.expirationDate=expirationdate; 55 } 56 } 57} 58 2.声明一个委托。 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4 5namespaceCreditCardForm 6{ 7 publicdelegatevoidValidateCreditCardFormEventHandler(objectsender,ValidateCreditCardFormEventArgsargs); 8} 9 3.定义事件 1 publiceventValidateCreditCardFormEventHandlerValidateCreditCardForm; 4.通事件发生后,通知其他对象的方法 1 2//这个方法是受保护的虚方法 3protectedvoidOnValidateCreditCardForm(ValidateCreditCardFormEventArgsargs) 4 { 5 if(ValidateCreditCardForm!=null) 6 handler(this,args); 7 } 这样几个步骤之后,控件的事件就写完了。大家试试! 有问题,我们下篇接着说! 今天写到这里,希望大家反馈信息,听听大家的想法! |
|
前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是行不通。如果大家开发的是WinForm中的事件,之前的定义可能没有什么大的问题,只是在效率方法欠考虑而且,还是可以运行的。
下面我们就回到ASP.NET中的事件。 大家也许看了我们之前定义的事件,确实,事件一般是那么定义的,但是那样定义事件后的,运行起来的效率不搞,因为那样定义事件后,编译器在编译事件代码的时候,会自动的为我们加入很多多线程安全的代码,就是说,虽然我们只是定义几行代码,大但是编译器为我们做了很多额外的事情,当然,这样代码的运行的效率可想而知。 在很多的时候,我们自定义控件的事件不是需要考虑多线程安全等问题的,所我们就要改变代码,使其运行的更加好,我们就采用下面的方法:显示的申明事件: 1 2//其实其实一个辅助的变量,用来做Hashtable中的”键“ 3privatestaticobjectValidateCreditCardFormKey=newobject(); 4 publiceventValidateCreditCardFormEventHandlerValidateCreditCardForm 5 { 6 add 7 { 8 Events.AddHandler(ValidateCreditCardFormKey,value); 9 } 10 remove 11 { 12 Events.RemoveHandler(ValidateCreditCardFormKey,value); 13 } 14 } 15 16 17 protectedvoidOnValidateCreditCardForm(ValidateCreditCardFormEventArgsargs) 18 { 19 ValidateCreditCardFormEventHandlerhandler=Events[ValidateCreditCardFormKey] 20 asValidateCreditCardFormEventHandler; 21 if(handler!=null) 22 handler(this,args); 23 } |
|
| |
TOP |
|
22# 大 中 小 发表于 2009-1-5 15:04 只看该作者
注意:其实就我们之前定义的事件的代码而言,编译器在在编译我们的代码的时候,也是编译成了上面的形式而且还额外的加上了一些安全的控制代码,这里,我们现在不要编译器生成,而是我们自己写出来,效率就高了。
还有就是:如果一个事件在事件列表(是一个hashtable)已经注册了,当页面上有两个相同我们自定义控件,我的控件的事件也只是在注册一次,效率也高了。 到这里一个事件就定义好了。现在做的事情就是要触发事件。即,点击“提交”按钮,就触发。我们先了理解一下流程: 点击“提交”,整个页面就向服务器提交了,之后就开始了页面的生命周期。 1.对页面进行解析,将原来页面中的源,如<asp:....></asp>这样的标记解析成相应的html代码,当把页面解析完之后,页面在服务器就是html的样式了。(我这里说的很粗略,没有必要说的那么详细)。 2.解析后的页面就开始检查,刚才是哪个控件引发的服务器回传,即,是点击了哪个按钮后,整个页面向服务器提交的,我们这里就是那个“提交”按钮。 3.解析后的页面检查“提交”按钮的name是否和控件(CreditCardForm)的name相同,如果相同。再检查控件 CreditCardForm实现了IPostBackEventHandler接口,如果实现了,就引发我们之前定义的事件。 这样,我们的控件就和真正的服务器控件没有两样了。(注意:上面的第3点:我们要按钮的name和CreditCardForm的name一样,这里的 name我们无法用自己手动来设置他们的一样,因为CreditCardForm的名字是有页面来设置的,页面将其设置为:this.UniqueID,所以我们只能将按钮的名字设置为this.UniqueID,这样就可以了),所以我们要重写CreditCardForm5的一些属性: |
|
| |
TOP |
|
23# 大 中 小 发表于 2009-1-5 15:05 只看该作者
1 protectedoverridestringSubmitButtonName
2 { 3 get 4 { 5 returnthis.UniqueID; 6 } 7 } 还有,每一次页面提交给服务器后,解析页面的this.UniqueID都不一样。而且,如果在页面中同时有两个CreditCardForm,我们也要保证两个控件的其他控件,如输入框等等的name也不一样,所以要分别重写name。 1protectedoverridestringPaymentMethodListName 2 { 3 get 4 { 5 returnthis.UniqueID+":PaymentMethod"; 6 } 7 } 8 9 protectedoverridestringCreditCardNoTextName 10 { 11 get 12 { 13 returnthis.UniqueID+":CreditCardNo"; 14 } 15 } 16 17 protectedoverridestringCardholderNameTextName 18 { 19 get 20 { 21 returnthis.UniqueID+":CardholderName"; 22 } 23 } 24 25 protectedoverridestringMonthListName 26 { 27 get 28 { 29 returnthis.UniqueID+":Month"; 30 } 31 } 32 33 protectedoverridestringYearListName 34 { 35 get 36 { 37 returnthis.UniqueID+":Year"; 38 } 39 } |
|
| |
TOP |
| vissd
项目经理
|
24# 大 中 小 发表于 2009-1-5 15:05 只看该作者
这里以后,下面我们就只要实现IPostBackEventHandler接口,就可以调用我们的事件了,实现IPostBackEventHandler接口,其实只有一个方法。而且也很简单,代码:
1 2 3//大家看看我们只是将之前的事件通知代码移到了这里。 4voidIPostBackEventHandler.RaisePostBackEvent(stringargs) 5 { 6 ValidateCreditCardFormEventArgsve=newValidateCreditCardFormEventArgs( 7 PaymentMethodText,CreditCardNoText,CardholderNameText,ExpirationDateText); 8 9 OnValidateCreditCardForm(ve); 10 } 这样以后,我们的控件就可以引发服务器回传了,即,当你点击“提交”按钮时,我们的浏览器的状态栏下面就有刷新的进度条了。 注意,还有一个问题啊,我们确实能够使得我们的控件向服务器提交信息,但是服务器怎么来得到我们的提交的信息呢? 并不是我们把信息向服务器提交后,就什么都不管了,然后服务器就”很听话的“进行验证。不是这样的,起码我们还要告诉服务器,我们提交了哪些要被验证的信息。 那么服务器这样接受到我们的信息,,很简单,只要实现一个接口就可以了--IPostBackDataHandler。 接口有两个方法,第一个就是LoadPostData方法,就是来获取我们的信息,并且判断我们这次提交的信息和上次有变化没有。 上面的方法返回一个布尔的值,如果返回true,就自动的调用下一个方法RaisePostDataChangedEvent,大家可以根据方法的英文看到他们的作用。 这里我们只是讲下LoadPostData方法,方法的完成写法是这样的: |
| |
TOP |
| vissd
项目经理
|
25# 大 中 小 发表于 2009-1-5 15:05 只看该作者
1boolLoadPostData(stringpostDataKey,NameValueCollectionvalues)
2{ 3 4} 看见方法不要害怕,方法的参数,前一个参数,我们不要管,只要看看后面的参数就可以了。 我们的信息的提交,都是在相应的输入框,下拉框中写好了,传给服务器的,其实是以:键值对,传了的. 键:就是我们输入框等的名字,name 值:就是输入的值。 其实NameValueCollection就是一个哈希表,来存放键值对的。 我们之前的所有输入的信息被包含成了一个NameValueCollection传到服务器,然后服务器就通过对应的“键”(name)来获取值,然后验证。 代码如下: 1 boolIPostBackDataHandler.LoadPostData(stringpostDataKey,NameValueCollectionvalues) 2 { 3 stringpaymentMethod=values[PaymentMethodListName]=="0"?"Master":"Visa"; 4 if(paymentMethod!=PaymentMethodText) 5 { 6 PaymentMethod=paymentMethod; 7 hasPaymentMethodChanged=true; 8 } 9 10 stringcreditCardNo=values[CreditCardNoTextName]; 11 if(creditCardNo!=CreditCardNoText) 12 { 13 CreditCardNoText=creditCardNo; 14 hasCreditCardNoChanged=true; 15 } 16 17 stringcardholderName=values[CardholderNameTextName]; 18 if(cardholderName!=CardholderNameText) 19 { 20 CardholderNameText=cardholderName; 21 hasCardholderNameChanged=true; 22 } 23 24 intmonth=int.Parse(values[MonthListName]); 25 intyear=int.Parse(values[YearListName]); 26 DateTimeexpirationDate=newDateTime(year,month,10); 27 if(expirationDate!=ExpirationDateText) 28 { 29 ExpirationDateText=expirationDate; 30 hasExpirationDateChanged=true; 31 } 32 33 34 if(!string.IsNullOrEmpty(values[SubmitButtonName])) 35 Page.RegisterRequiresRaiseEvent(this); 36 37 returnhasExpirationDateChanged|| 38 hasCreditCardNoChanged|| 39 hasPaymentMethodChanged|| 40 hasCardholderNameChanged; 41 42 } |
| |
TOP |
| vissd
项目经理
|
26# 大 中 小 发表于 2009-1-5 15:08 只看该作者
这样,我们整个控件就写完了,不知道大家懂了没:有问题回复!完整代码如下:
1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4usingSystem.Web; 5usingSystem.Web.UI; 6usingSystem.Web.UI.WebControls; 7usingSystem.Collections; 8 9usingSystem.Collections.Specialized; 10 11namespaceCreditCardForm 12{ 13 publicclassCreditCardForm6:CreditCardForm5,IPostBackEventHandler,IPostBackDataHandler 14 { 15 #regionoverridename 16 protectedoverridestringPaymentMethodListName 17 { 18 get 19 { 20 returnthis.UniqueID+":PaymentMethod"; 21 } 22 } 23 24 protectedoverridestringCreditCardNoTextName 25 { 26 get 27 { 28 returnthis.UniqueID+":CreditCardNo"; 29 } 30 } 31 32 protectedoverridestringCardholderNameTextName 33 { 34 get 35 { 36 returnthis.UniqueID+":CardholderName"; 37 } 38 } 39 40 protectedoverridestringMonthListName 41 { 42 get 43 { 44 returnthis.UniqueID+":Month"; 45 } 46 } 47 48 protectedoverridestringYearListName 49 { 50 get 51 { 52 returnthis.UniqueID+":Year"; 53 } 54 } 55 56 protectedoverridestringSubmitButtonName 57 { 58 get 59 { 60 returnthis.UniqueID; 61 } 62 } 63 #endregion 64 #regionprorerty 65 66 publicstringPaymentMethodText 67 { 68 get 69 { 70 returnViewState["PaymentMethod"]!=null?(string)ViewState["PaymentMethod"]:string.Empty; 71 } 72 set 73 { 74 ViewState["PaymentMethod"]=value; 75 } 76 } 77 78 79 publicstringCreditCardNoText 80 { 81 get 82 { 83 returnViewState["CreditCardNo"]!=null?(string)ViewState["CreditCardNo"]:string.Empty; 84 } 85 set 86 { 87 ViewState["CreditCardNo"]=value; 88 } 89 } 90 91 publicstringCardholderNameText 92 { 93 get 94 { 95 returnViewState["CardholderName"]!=null?(string)ViewState["CardholderName"]:string.Empty; 96 } 97 set 98 { 99 ViewState["CardholderName"]=value; 100 } 101 } 102 103 publicDateTimeExpirationDateText 104 { 105 get 106 { 107 returnViewState["ExpirationDate"]!=null?(DateTime)ViewState["ExpirationDate"]:DateTime.Now; 108 } 109 set 110 { 111 ViewState["ExpirationDate"]=value; 112 } 113 } 114 115 116 #endregion 117 118 #regionevents 119 privatestaticobjectValidateCreditCardFormKey=newobject(); 120 publiceventValidateCreditCardFormEventHandlerValidateCreditCardForm 121 { 122 add 123 { 124 Events.AddHandler(ValidateCreditCardFormKey,value); 125 } 126 remove 127 { 128 Events.RemoveHandler(ValidateCreditCardFormKey,value); 129 } 130 } 131 132 133 protectedvoidOnValidateCreditCardForm(ValidateCreditCardFormEventArgsargs) 134 { 135 ValidateCreditCardFormEventHandlerhandler=Events[ValidateCreditCardFormKey] 136 asValidateCreditCardFormEventHandler; 137 if(handler!=null) 138 handler(this,args); 139 } 140 141 #endregion 142 voidIPostBackEventHandler.RaisePostBackEvent(stringargs) 143 { 144 ValidateCreditCardFormEventArgsve=newValidateCreditCardFormEventArgs( 145 PaymentMethodText,CreditCardNoText,CardholderNameText,ExpirationDateText); 146 147 OnValidateCreditCardForm(ve); 148 } 149 150 privateboolhasPaymentMethodChanged; 151 privateboolhasCreditCardNoChanged; 152 privateboolhasCardholderNameChanged; 153 privateboolhasExpirationDateChanged; 154 155 boolIPostBackDataHandler.LoadPostData(stringpostDataKey,NameValueCollectionvalues) 156 { 157 stringpaymentMethod=values[PaymentMethodListName]=="0"?"Master":"Visa"; 158 if(paymentMethod!=PaymentMethodText) 159 { 160 PaymentMethod=paymentMethod; 161 hasPaymentMethodChanged=true; 162 } 163 164 stringcreditCardNo=values[CreditCardNoTextName]; 165 if(creditCardNo!=CreditCardNoText) 166 { 167 CreditCardNoText=creditCardNo; 168 hasCreditCardNoChanged=true; 169 } 170 171 stringcardholderName=values[CardholderNameTextName]; 172 if(cardholderName!=CardholderNameText) 173 { 174 CardholderNameText=cardholderName; 175 hasCardholderNameChanged=true; 176 } 177 178 intmonth=int.Parse(values[MonthListName]); 179 intyear=int.Parse(values[YearListName]); 180 DateTimeexpirationDate=newDateTime(year,month,10); 181 if(expirationDate!=ExpirationDateText) 182 { 183 ExpirationDateText=expirationDate; 184 hasExpirationDateChanged=true; 185 } 186 187 188 if(!string.IsNullOrEmpty(values[SubmitButtonName])) 189 Page.RegisterRequiresRaiseEvent(this); 190 191 returnhasExpirationDateChanged|| 192 hasCreditCardNoChanged|| 193 hasPaymentMethodChanged|| 194 hasCardholderNameChanged; 195 196 } 197 198 voidIPostBackDataHandler.RaisePostDataChangedEvent() 199 { 200 boolhasChanged; 201 hasChanged=hasCardholderNameChanged|| 202 hasCreditCardNoChanged|| 203 hasPaymentMethodChanged|| 204 hasExpirationDateChanged; 205 206 if(hasChanged) 207 { 208 209 ValidateCreditCardFormEventArgsargs=newValidateCreditCardFormEventArgs( 210 PaymentMethod,CreditCardNoText,CardholderNameText,ExpirationDateText); 211 212 OnValidateCreditCardForm(args); 213 } 214 } 215 216 } 217} 218 |
| |
TOP |
| vissd
项目经理
|
27# 大 中 小 发表于 2009-1-5 15:08 只看该作者
第四章 组合控件开发CompositeControl大家好,今天我们来实现一个自定义的控件,之前我们已经知道了,要开发自定义的控件一般继承三个基类:Control,WebControl,还有一个就是今天要说的CompositeControl。 大家也许还记得,之前的开发的控件基本上都是我们自己从头到尾的写一些控件的标记,如<table.....>之类的,而且还有一个大的问题:我们为了使得我们的控件更加的好用,专业,我们还实现了大量的接口,和自己写很多的事件.这样开发控件的时间就加大了。其实我们可以利用ASP.NET中已经有的控件,经过我们包装,实现我们自定义控件。大家可能认为这和用户控件差不多的,但是继承CompositeConytol的控件的自定义控件的灵活性和复用行更好,而且还还添加样式。
还一个更加重要的就是我们不必要实现接口,比如,引发回传的IPostBackEventHandler接口,接受数据的IPostBackDataHandler接口。大家还记得我们之前开发控件中的的那个Button还要申明name为 this.UniqueID,现在我们都不需要了,因为我们要包装的那些服务器的控件,如TextBox,他们都已经实现了这些。 本章准备开发一个大家都熟知的Login登录控件。 大家先看看效果: ![]() 其实分析起来,这个控件是由一些已有的控件组合而成的,分别是: 两个Label,两个TextBox,和一个Button 下面我们就来开发: 首先,还是先继承CompositeControl; 1 publicclassLogin:CompositeControl 然后把就申明我们要组合的控件,如上所说的: 1 #region要组合的控件 2 LabellbUserName; 3 LabellbUserPassward; 4 TextBoxtxtUserName; 5 TextBoxtxtUserPassward; 6 ButtonsubmitButton; 7 #endregion |
| |
TOP |
| vissd
项目经理
|
28# 大 中 小 发表于 2009-1-5 15:09 只看该作者
把控件申明了之后只要初始化,并且将这些控件整合成我们的Login 控件就可以了。这么做呢?
其实开发组合控件很简单,一般只要重写一个方法就可以了。这个方法就是来初始化并且整合那些已经申明了的小控件的。如下: 1 #region重写方法CreateChildControls 2 3 protectedoverridevoidCreateChildControls() 4 { 5 //清空控件,大家可以理解为:初始化一张白纸,好让我们来画画 6 7 Controls.Clear(); 8 9 //初始化控件lbUserName 10 lbUserName=newLabel(); 11 lbUserName.Text="用户名:"; 12 lbUserName.ID="lbUserName"; 13 //把控件添加到我们的组合控件中 14 Controls.Add(lbUserName); 15 16 //初始化控件lbUserPassward 17 lbUserPassward=newLabel(); 18 lbUserPassward.Text="密 码:"; 19 lbUserPassward.ID="lbUserPassward"; 20 Controls.Add(lbUserPassward); 21 22 //初始化控件txtUserName 23 24 txtUserName=newTextBox(); 25 txtUserName.ID="txtUserName"; 26 txtUserName.Width=Unit.Percentage(60); 27 Controls.Add(txtUserName); 28 29 //初始化控件txtUserPassward 30 txtUserPassward=newTextBox(); 31 txtUserPassward.ID="txtUserPassward"; 32 txtUserPassward.Width=Unit.Percentage(60); 33 Controls.Add(txtUserPassward); 34 35 //初始化控件submitButton 36 submitButton =newButton(); 37 submitButton.Text="提交"; 38 submitButton.CommandName="Validate"; 39 Controls.Add(submitButton); 40 41 告诉编译器,控件已经初始化了 42 ChildControlsCreated=true; 43 } 44 #endregion |
| |
TOP |
| vissd
项目经理
|
29# 大 中 小 发表于 2009-1-5 15:09 只看该作者
大家特别要注意,最后的那句ChildControlsCreated属性,一定要申明,因为在页面的声明周期的任何时候可能调用上面的那个方法,如果不申明ChildControlsCreated,那么这个方法就会被反复的调用,那么我们控件的状态都会丢失。
如果申明了ChildControlsCreated=true,那么这个方法就调用一次。 经过上面的步骤之后,其实我们的控件就已经开发完成了。 可能我们还想进一步的向我们ASP.NET的标准的Login控件靠拢.那么我们的控件还缺少什么? 属性,事件!!! 以前我们定义属性都是用的ViewState["..."],但是这里就不同了。因为我们的控件是有很多的小的控件组合起来的,比如,我们修改“用户名:”的那个Label,我们想改的是那个Label的属性,还是看看效果图: 改前的图: 改后的图 ![]() 就是说,我们想把子控件的属性如Text,name等等,把这些属性上升呈现为组合控件Login的属性。 怎么做? 也很简单的:如下: 1 publicstringUserNameLabelText 2 { 3 get 4 { 5 EnsureChildControls(); 6 returnlbUserName.Text; 7 } 8 set 9 { 10 EnsureChildControls(); 11 lbUserName.Text=value; 12 } 13 } |
| |
TOP |
| vissd
项目经理
|
30# 大 中 小 发表于 2009-1-5 15:10 只看该作者
这样我们就把那个显示用户名的Label的Text属性显示为了Login控件的UserNameLabelText属性。大家要注意EnsureChildControls(); 这个方法的调用。其实是个保险的:确保我们要显示属性的那个控件已经创建,已经初始化了。
大家可以根据需要显示更加多的属性。也可以自己定义一些属性,还是像以前那样,可以用ViewState[''.."] 如果到这里为止,就差不多了。大家可以按按照上面的方法来写控件。 大家可以看见,控件的呈现很乱。那些Label.TextBox都布局的很乱。其实你可以根据需要来将上面的那些控件排列的更加好看些,只要重写一个方法就行了: 1protectedoverridevoidRenderContents(HtmlTextWriterwriter) 还是像之前一样,我们想把控件用一个Table来布局,先这样 1 protectedoverrideHtmlTextWriterTagTagKey 2 { 3 get 4 { 5 returnHtmlTextWriterTag.Table; 6 } 7 } 然后再把那些Label,TextBox,Button放到table的行和列中就行了。如下: 1protectedoverridevoidRenderContents(HtmlTextWriterwriter) 2 { 3 4 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 5 6 writer.RenderBeginTag(HtmlTextWriterTag.Td); 7 lbUserName.RenderControl(writer); 8 writer.RenderEndTag();//td的结束 9 10 writer.RenderBeginTag(HtmlTextWriterTag.Td); 11 txtUserName.RenderControl(writer); 12 writer.RenderBeginTag(); 13 14 writer.RenderBeginTag();//tr的结束 15 16 //*********************************************** 17 18 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 19 20 writer.RenderBeginTag(HtmlTextWriterTag.Td); 21 lbUserPassward.RenderControl(writer); 22 writer.RenderEndTag();//td的结束 23 24 writer.RenderBeginTag(HtmlTextWriterTag.Td); 25 txtUserPassward.RenderControl(writer); 26 writer.RenderBeginTag(); 27 28 writer.RenderBeginTag();//tr的结束 29 30 //*********************************************** 31 32 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 33 34 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 35 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 36 writer.RenderBeginTag(HtmlTextWriterTag.Td); 37 submitButton.RenderControl(writer); 38 writer.RenderBeginTag(); 39 40 writer.RenderBeginTag();//tr的结束 41 42 43 44 45 } |
|
这样,我们的控件就写完了。
我们的控件还差事件。我们在下篇将“事件的冒泡”。 顺便做个调查:大家想看开发控件的视频吗,我正在录制。 完整的代码:如下: 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4usingSystem.Web; 5usingSystem.Web.UI; 6usingSystem.Web.UI.WebControls; 7usingSystem.ComponentModel; 8 9namespaceLoginControl 10{ 11 publicclassLogin:CompositeControl,IPostBackDataHandler 12 { 13 #region要组合的控件 14 LabellbUserName; 15 LabellbUserPassward; 16 TextBoxtxtUserName; 17 TextBoxtxtUserPassward; 18 ButtonsubmitButton; 19 #endregion 20 21 22 #region重写方法CreateChildControls 23 24 protectedoverridevoidCreateChildControls() 25 { 26 Controls.Clear(); 27 28 //初始化控件lbUserName 29 lbUserName=newLabel(); 30 lbUserName.Text="用户名:"; 31 lbUserName.ID="lbUserName"; 32 //把控件添加到我们的组合控件中 33 Controls.Add(lbUserName); 34 35 //初始化控件lbUserPassward 36 lbUserPassward=newLabel(); 37 lbUserPassward.Text="密 码:"; 38 lbUserPassward.ID="lbUserPassward"; 39 Controls.Add(lbUserPassward); 40 41 42 txtUserName=newTextBox(); 43 txtUserName.ID="txtUserName"; 44 txtUserName.Width=Unit.Percentage(60); 45 Controls.Add(txtUserName); 46 47 txtUserPassward=newTextBox(); 48 txtUserPassward.ID="txtUserPassward"; 49 txtUserPassward.Width=Unit.Percentage(60); 50 Controls.Add(txtUserPassward); 51 52 submitButton =newButton(); 53 submitButton.Text="提交"; 54 submitButton.CommandName="Validate"; 55 Controls.Add(submitButton); 56 57 ChildControlsCreated=true; 58 } 59 #endregion 60 #region将组合的子控件的属性呈现为组合控件的属性 61 62 publicstringUserNameLabelText 63 { 64 get 65 { 66 EnsureChildControls(); 67 returnlbUserName.Text; 68 } 69 set 70 { 71 EnsureChildControls(); 72 lbUserName.Text=value; 73 } 74 } 75 76 publicstringUserPasswardLabelText 77 { 78 get 79 { 80 EnsureChildControls(); 81 returnlbUserPassward.Text; 82 } 83 set 84 { 85 EnsureChildControls(); 86 lbUserPassward.Text=value; 87 } 88 } 89 90 publicstringSubmitButtonText 91 { 92 get 93 { 94 EnsureChildControls(); 95 returnsubmitButton.Text; 96 } 97 set 98 { 99 EnsureChildControls(); 100 submitButton=value; 101 } 102 } 103 104 105 #endregion 106 107 #region组合控件呈现的样式 108 protectedoverrideHtmlTextWriterTagTagKey 109 { 110 get 111 { 112 returnHtmlTextWriterTag.Table; 113 } 114 } 115 116 protectedoverridevoidRenderContents(HtmlTextWriterwriter) 117 { 118 119 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 120 121 writer.RenderBeginTag(HtmlTextWriterTag.Td); 122 lbUserName.RenderControl(writer); 123 writer.RenderEndTag();//td的结束 124 125 writer.RenderBeginTag(HtmlTextWriterTag.Td); 126 txtUserName.RenderControl(writer); 127 writer.RenderBeginTag(); 128 129 writer.RenderBeginTag();//tr的结束 130 131 //*********************************************** 132 133 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 134 135 writer.RenderBeginTag(HtmlTextWriterTag.Td); 136 lbUserPassward.RenderControl(writer); 137 writer.RenderEndTag();//td的结束 138 139 writer.RenderBeginTag(HtmlTextWriterTag.Td); 140 txtUserPassward.RenderControl(writer); 141 writer.RenderBeginTag(); 142 143 writer.RenderBeginTag();//tr的结束 144 145 //*********************************************** 146 147 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 148 149 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 150 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 151 writer.RenderBeginTag(HtmlTextWriterTag.Td); 152 submitButton.RenderControl(writer); 153 writer.RenderBeginTag(); 154 155 writer.RenderBeginTag();//tr的结束 156 157 158 159 160 } 161 #endregion 162 163 164 165 } 166} 167 |
|
| |
TOP |
| vissd
项目经理
|
32# 大 中 小 发表于 2009-1-5 15:12 只看该作者
第四章 组合控件开发CompositeControl 后篇 --事件冒泡 我们上一篇已经开发一个登录的组合控件,但是我们把控件的事件的这个问题没有解决,现在我们就来看看这个问题。
因为我们的组合控件Login是由一些已经存在的服务器控件的组合的,这样就省却了我们很多的麻烦,上篇中我们已经把子控件的一些属性,如Text等,显示呈现为了组合控件的属性。我们将之称为“属性的冒泡”(我自己这样认为的)。 我们现在来想下:其实我们点击“提交”按钮,我们就想把控件中信息发送给服务器,然后验证。即,我们点击的是“提交”按钮,但是触发的确实Login控件的验证事件。也就是说,我们应该把子控件-button的事件,上升冒泡成为Login的事件。 现在我们就正式讲讲怎么来事件冒泡。 对于事件的一些步骤,大家应该还记得: 1。定义一个数据类,用来当发生事件时,我们把一些信息携带。在本控件中,当我们点击“提交”按钮时,我们就把用户名和密码作为数据送到服务器。所以我们的数据类包含两个信息:如下: 1publicclassValidateEventArgs:EventArgs 2 { 3 privatestringuserName; 4 privatestringuserPassward; 5 6 publicstringUserName 7 { 8 get 9 { 10 return userName; 11 } 12 } 13 14 publicstringUserPassward 15 { 16 get 17 { 18 returnuserPassward; 19 } 20 } 21 22 publicValidateEventArgs(stringusername,stringuserpassward) 23 { 24 this.userName=username; 25 this.userPassward=userpassward; 26 } 27 } |
| |
TOP |
| vissd
项目经理
|
33# 大 中 小 发表于 2009-1-5 15:12 只看该作者
相信大家对上面的代码不陌生!!!
2.我们来定义一个委托: 1publicdelegatevoidValidateEventHandler(objectsender,ValidateEventArgsargs); 3.定义事件。 1 privatestaticreadonlyobjectValidateEventKey=newobject(); 2 publiceventValidateEventHandlerValidateUserInfoChanged 3 { 4 add 5 { 6 Events.AddHandler(ValidateEventKey,value); 7 } 8 remove 9 { 10 Events.RemoveHandler(ValidateEventKey,value); 11 } 12 } 13 14 protectedvirtualvoidOnValidateChanged(ValidateEventArgsargs) 15 { 16 ValidateEventHandlerhandler=Events[ValidateEventKey]asValidateEventHandler; 17 if(handler!=null) 18 handler(this,args); 19 } 20 4.好了;准备都做好了,下面我们只要把这个事件冒泡成为Login的控件的就行了。其实很简单的。只要重写一个方法就行了。 如下: 1protectedoverrideboolOnBubbleEvent(objectsource,EventArgsargs) 2 { 3 boolhandled=false; 4 5 CommandEventArgsce=argsasCommandEventArgs; 6 if(ce!=null&&ce.CommandName=="Validate") 7 { 8 handled=true; 9 stringuserName=this.txtUserName.Text; 10 stringuserPassward=this.txtUserPassward.Text; 11 12 //把信息输入 13 ValidateEventArgsve=newValidateEventArgs(userName,userPassward); 14 OnValidateChanged(ve); 15 } 16 returnhandled; 17 } |
| |
TOP |
| vissd
项目经理
|
34# 大 中 小 发表于 2009-1-5 15:12 只看该作者
好了,完了,就这样了。
完整代码附上: 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Text; 4usingSystem.Web; 5usingSystem.Web.UI; 6usingSystem.Web.UI.WebControls; 7usingSystem.ComponentModel; 8 9namespaceLoginControl 10{ 11 publicclassLogin:CompositeControl 12 { 13 #region要组合的控件 14 LabellbUserName; 15 LabellbUserPassward; 16 TextBoxtxtUserName; 17 TextBoxtxtUserPassward; 18 ButtonsubmitButton; 19 #endregion 20 21 22 #region重写方法CreateChildControls 23 24 protectedoverridevoidCreateChildControls() 25 { 26 Controls.Clear(); 27 28 //初始化控件lbUserName 29 lbUserName=newLabel(); 30 lbUserName.Text="用户名:"; 31 lbUserName.ID="lbUserName"; 32 //把控件添加到我们的组合控件中 33 Controls.Add(lbUserName); 34 35 //初始化控件lbUserPassward 36 lbUserPassward=newLabel(); 37 lbUserPassward.Text="密 码:"; 38 lbUserPassward.ID="lbUserPassward"; 39 Controls.Add(lbUserPassward); 40 41 42 txtUserName=newTextBox(); 43 txtUserName.ID="txtUserName"; 44 txtUserName.Width=Unit.Percentage(60); 45 Controls.Add(txtUserName); 46 47 txtUserPassward=newTextBox(); 48 txtUserPassward.ID="txtUserPassward"; 49 txtUserPassward.Width=Unit.Percentage(60); 50 Controls.Add(txtUserPassward); 51 52 submitButton =newButton(); 53 submitButton.Text="提交"; 54 submitButton.CommandName="Validate"; 55 Controls.Add(submitButton); 56 57 ChildControlsCreated=true; 58 } 59 #endregion 60 #region将组合的子控件的属性呈现为组合控件的属性 61 62 publicstringUserNameLabelText 63 { 64 get 65 { 66 EnsureChildControls(); 67 returnlbUserName.Text; 68 } 69 set 70 { 71 EnsureChildControls(); 72 lbUserName.Text=value; 73 } 74 } 75 76 publicstringUserPasswardLabelText 77 { 78 get 79 { 80 EnsureChildControls(); 81 returnlbUserPassward.Text; 82 } 83 set 84 { 85 EnsureChildControls(); 86 lbUserPassward.Text=value; 87 } 88 } 89 90 publicstringSubmitButtonText 91 { 92 get 93 { 94 EnsureChildControls(); 95 returnsubmitButton.Text; 96 } 97 set 98 { 99 EnsureChildControls(); 100 submitButton.Text =value; 101 } 102 } 103 104 105 #endregion 106 107 #region组合控件呈现的样式 108 protectedoverrideHtmlTextWriterTagTagKey 109 { 110 get 111 { 112 returnHtmlTextWriterTag.Table; 113 } 114 } 115 116 protectedoverridevoidRenderContents(HtmlTextWriterwriter) 117 { 118 119 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 120 121 writer.RenderBeginTag(HtmlTextWriterTag.Td); 122 lbUserName.RenderControl(writer); 123 writer.RenderEndTag();//td的结束 124 125 writer.RenderBeginTag(HtmlTextWriterTag.Td); 126 txtUserName.RenderControl(writer); 127 writer.RenderEndTag(); 128 129 writer.RenderEndTag();//tr的结束 130 131 //*********************************************** 132 133 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 134 135 writer.RenderBeginTag(HtmlTextWriterTag.Td); 136 lbUserPassward.RenderControl(writer); 137 writer.RenderEndTag();//td的结束 138 139 writer.RenderBeginTag(HtmlTextWriterTag.Td); 140 txtUserPassward.RenderControl(writer); 141 writer.RenderEndTag(); 142 143 writer.RenderEndTag();//tr的结束 144 145 //*********************************************** 146 147 writer.RenderBeginTag(HtmlTextWriterTag.Tr); 148 149 writer.AddAttribute(HtmlTextWriterAttribute.Colspan,"2"); 150 writer.AddAttribute(HtmlTextWriterAttribute.Align,"center"); 151 writer.RenderBeginTag(HtmlTextWriterTag.Td); 152 submitButton.RenderControl(writer); 153 writer.RenderEndTag(); 154 155 writer.RenderEndTag();//tr的结束 156 157 158 159 160 } 161 #endregion 162 163 #region事件 164 privatestaticreadonlyobjectValidateEventKey=newobject(); 165 publiceventValidateEventHandlerValidateUserInfoChanged 166 { 167 add 168 { 169 Events.AddHandler(ValidateEventKey,value); 170 } 171 remove 172 { 173 Events.RemoveHandler(ValidateEventKey,value); 174 } 175 } 176 177 protectedvirtualvoidOnValidateChanged(ValidateEventArgsargs) 178 { 179 ValidateEventHandlerhandler=Events[ValidateEventKey]asValidateEventHandler; 180 if(handler!=null) 181 handler(this,args); 182 } 183 184 #endregion 185 186 #region冒泡 187 188 protectedoverrideboolOnBubbleEvent(objectsource,EventArgsargs) 189 { 190 boolhandled=false; 191 192 CommandEventArgsce=argsasCommandEventArgs; 193 if(ce!=null&&ce.CommandName=="Validate") 194 { 195 handled=true; 196 stringuserName=this.txtUserName.Text; 197 stringuserPassward=this.txtUserPassward.Text; 198 199 //把信息输入 200 ValidateEventArgsve=newValidateEventArgs(userName,userPassward); 201 OnValidateChanged(ve); 202 } 203 returnhandled; 204 } 205 #endregion 206 207 208 209 } 210} 211 |
| |
TOP |
| vissd
项目经理
|
35# 大 中 小 发表于 2009-1-5 15:12 只看该作者
第五章 模板控件开发 大家好,我们今天来开发一个模板控件。
其实开发一个模板控件比开发一个组合控件更加简单,所以这章不难。 开发一个模板控件一般都继承CompositeControl,因为继承这个基类后,我们就省却了很多的麻烦。所以本章我们开发的模板控件也继承于CompositeControl。大家应该还记得我们上章开发那个登录Login控件吧,如下: ![]() 以上就是我们之前开发的登录控件,现在我们来改造它。我们的现在的这个登录控件的输入用户名和密码的控件是TextBox,我们有时候可能想把TextBox 换成DropdownList,或者其他的控件。也就说,我们想定制这个登录的控件。那么,我们就要模板了。 首先来看看我们本章实现控件的最后效果: ![]() ![]() 大家看见没,这样我们就可以定制这个控件了。好了,我们来实现吧。 首先,我们让我们的模板控件继承上章的那个组合的Login控件: Code 1 public class TemplateLoginControl:Login |
| |
TOP |
| vissd
项目经理
|
36# 大 中 小 发表于 2009-1-5 15:13 只看该作者
然后,我们就声明我们的模板:
Code 1 #region//声明模板 2 private ITemplate loginUserNameTemplate; 3 4 [Browsable (false )]//我们不想在属性窗口中看见它 5 [TemplateContainer (typeof(TemplateLoginControl ))]//我们的模板是包含在找个控件中的, 6 [PersistenceMode (PersistenceMode.InnerProperty )]//模板中内容很复杂的,比如你可以拖入很多的控件 7 public ITemplate LoginUserNameTemplate 8 { 9 get 10 { 11 return loginUserNameTemplate; 12 } 13 set 14 { 15 loginUserNameTemplate = value; 16 } 17 18 } 19 20 private ITemplate loginUserPasswardTemplate; 21 [Browsable(false)]//我们不想在属性窗口中看见它 22 [TemplateContainer(typeof(TemplateLoginControl))]//我们的模板是包含在找个控件中的, 23 [PersistenceMode(PersistenceMode.InnerProperty)]//模板中内容很复杂的,比如你可以拖入很多的控件 24 public ITemplate LoginUserPasswardTemplate 25 { 26 get 27 { 28 return loginUserPasswardTemplate; 29 } 30 set 31 { 32 loginUserPasswardTemplate = value; 33 } 34 } 35 #endregion |
| |
TOP |
| vissd
项目经理
|
37# 大 中 小 发表于 2009-1-5 15:13 只看该作者
正如前面所说的,我们只是想定制两个输入信息的模板,大家可以根据需要,声明更多的模板。如,大家还可以把显示的用户名的那些Label换成模板定制。
其实编写模板控件比编写一个组合控件更加的简单。大家稍后就可以体会到了。 好了,声明完了模板之后,我们的控件写了一大半了,还差一点。大家想想是什么??? 对了,就是应用这些模板了。如下: Code 1 protectedoverridevoidCreateChildControls() 2 { 3 Controls.Clear(); 4 if(loginUserNameTemplate!=null) 5 loginUserNameTemplate.InstantiateIn(this); 6 else 7 base.CreateChildControls(); 8 if(loginUserPasswardTemplate!=null) 9 loginUserPasswardTemplate.InstantiateIn(this); 10 else 11 base.CreateChildControls(); 12 13 ChildControlsCreated=true; 14 15 16 } 我想,大家对这个方法不陌生。因为我们之前的组合控件也是重写了这个方法。到这里,就写完了。 大家可能还有疑问,为什么这样重写 CreateChildControls()方法后,就会达到我们的效果? 下面,我就来将这个方法和之前的那个组合控件的 CreateChildControls()方法比较一下,也顺便讲下模板的内幕。 先看组合控件的 CreateChildControls()方法,见下: Code 1protectedoverridevoidCreateChildControls() 2 { 3 Controls.Clear(); 4 5 //初始化控件lbUserName 6 lbUserName=newLabel(); 7 lbUserName.Text="用户名:"; 8 lbUserName.ID="lbUserName"; 9 //把控件添加到我们的组合控件中 10 Controls.Add(lbUserName); 11 12 //初始化控件lbUserPassward 13 lbUserPassward=newLabel(); 14 lbUserPassward.Text="密 码:"; 15 lbUserPassward.ID="lbUserPassward"; 16 Controls.Add(lbUserPassward); 17 18 19 txtUserName=newTextBox(); 20 txtUserName.ID="txtUserName"; 21 txtUserName.Width=Unit.Percentage(60); 22 Controls.Add(txtUserName); 23 24 txtUserPassward=newTextBox(); 25 txtUserPassward.ID="txtUserPassward"; 26 txtUserPassward.Width=Unit.Percentage(60); 27 Controls.Add(txtUserPassward); 28 29 submitButton =newButton(); 30 submitButton.Text="提交"; 31 submitButton.CommandName="Validate"; 32 Controls.Add(submitButton); 33 34 ChildControlsCreated=true; 35 } |
| |
TOP |
| vissd
项目经理
|
38# 大 中 小 发表于 2009-1-5 15:13 只看该作者
1.首先,在之前的组合控件中,我们是把那个TextBox,Label硬编码到了生成和初始化控件的方法CreateChildControls()中。而在模板控件中,我们没有这样做,我们只是简单的调用了模板的一个方法: InstantiateIn()。实际上,这个方法是个晚绑定。
为什么是晚绑定?先来看看下面: ![]() 假设我们想用个下拉框来输入用户名,我们肯定要设计下拉框的属性,如 name,id,等等,当我们设置好后,就形如这样了: Code 1<asp:DropDownListID="mylist"runat="server"BackColor="red"></asp:DropDownList> 其实这样和在CreateChildControls()中声明是一样的,形如: Code 1 DropDownListmylist=newDropDownList(); 2 mylist.ID="mylist"; 3 mylist.Items=newListItemCollection(); 4 Controls.Add(mylist); 5 其实模板控件的方法InstantiateIn()就是将之前的那个<ASp:dropdownlist....>代码转换为 DropDownList mylist=new DropDownList()... 不知道大家清楚,说到底就是个晚绑定!!! 到这里,模板控件完了,大家编译后,就后看到下面的控件: ![]() 然后,我们就在html代码开发声明:如下: |
| |
TOP |
| vissd
项目经理
|
39# 大 中 小 发表于 2009-1-5 15:13 只看该作者
Code
1 <cc1:TemplateLoginCrunat="server"> 2 <LoginUserNameTemplate> 3 4 </LoginUserNameTemplate> 5 <LoginUserPasswardTemplate> 6 7 </LoginUserPasswardTemplate> 8 </cc1:TemplateLoginControl> 9 很多时候,我们不喜欢这样,因为我们更加喜欢图形化的设置,如下: ![]() 这样更加友好些。其实这也不难,只要加个设计器就可以了。 设计器是个类。在ASP.NET有很多的设计器,如ControlDesigner,CompositeControlDesigner.等等。 我们的设计器的一般都继承已有的设计器类。在这里我不多讲,大家需要的话,我专们用一章来讲。 Code 1public class MyLoginDesigner : CompositeControlDesigner 2 { 3 public override void Initialize(IComponent component) 4 { 5 base.Initialize(component); 6 SetViewFlags(ViewFlags.TemplateEditing, true); 7 } 8 9 public override string GetDesignTimeHtml() 10 { 11 TemplateLoginControl control = Component as TemplateLoginControl; 12 if (control != null) 13 { 14 if (control.LoginUserNameTemplate == null) 15 { 16 return CreatePlaceHolderDesignTimeHtml("请您编辑用户名的模板"); 17 18 } 19 20 if (control.LoginUserPasswardTemplate == null) 21 { 22 return CreatePlaceHolderDesignTimeHtml("请您编辑用户密码的模板"); 23 } 24 } 25 return base.GetDesignTimeHtml(); 26 } 27 28 private TemplateGroupCollection tempgc; 29 public override TemplateGroupCollection TemplateGroups 30 { 31 get 32 { 33 if (tempgc == null) 34 { 35 36 tempgc = base.TemplateGroups; 37 38 TemplateGroup loginUserNameTemplate = new TemplateGroup("UserNameTemplate"); 39 loginUserNameTemplate.AddTemplateDefinition (new TemplateDefinition (this,"UserNameTemplate", 40 Component,"UserNameTemplate",false )); 41 tempgc.Add (loginUserNameTemplate ); 42 43 TemplateGroup loginPasswardNameTemplate = new TemplateGroup("UserPasswardTemplate"); 44 loginPasswardNameTemplate.AddTemplateDefinition(new TemplateDefinition(this, "UserPasswardTemplate", 45 Component,"UserPasswardTemplate",false )); 46 tempgc.Add(loginPasswardNameTemplate); 47 } 48 return tempgc; 49 } 50 } 51 } |
| |
TOP |
|
40# 大 中 小 发表于 2009-1-5 15:14 只看该作者
然后在这样: Code
1 [Designer (typeof (MyLoginDesigner ))] 2 public class TemplateLoginControl:Login 一切就OK了,写的有些催促,大家有问题我一定回复。 完整代码如下: Code 1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Web; 5using System.Web.UI; 6using System.Web.UI.WebControls; 7using System.ComponentModel; 8using System.Web.UI.Design; 9using System.Web.UI.Design.WebControls ; 10using System.Collections ; 11 12 13 14 15namespace LoginControl 16{ 17 [Designer (typeof (MyLoginDesigner ))] 18 public class TemplateLoginControl:Login 19 { 20 //声明模板#region//声明模板 21 private ITemplate loginUserNameTemplate; 22 23 [Browsable (false )]//我们不想在属性窗口中看见它 24 [TemplateContainer (typeof(TemplateLoginControl ))]//我们的模板是包含在找个控件中的, 25 [PersistenceMode (PersistenceMode.InnerProperty )]//模板中内容很复杂的,比如你可以拖入很多的控件 26 public ITemplate LoginUserNameTemplate 27 { 28 get 29 { 30 return loginUserNameTemplate; 31 } 32 set 33 { 34 loginUserNameTemplate = value; 35 } 36 37 } 38 39 private ITemplate loginUserPasswardTemplate; 40 [Browsable(false)]//我们不想在属性窗口中看见它 41 [TemplateContainer(typeof(TemplateLoginControl))]//我们的模板是包含在找个控件中的, 42 [PersistenceMode(PersistenceMode.InnerProperty)]//模板中内容很复杂的,比如你可以拖入很多的控件 43 public ITemplate LoginUserPasswardTemplate 44 { 45 get 46 { 47 return loginUserPasswardTemplate; 48 } 49 set 50 { 51 loginUserPasswardTemplate = value; 52 } 53 } 54 #endregion 55 重写创建控件的方法#region 重写创建控件的方法 56 57 protected override void CreateChildControls() 58 { 59 Controls.Clear(); 60 if (loginUserNameTemplate != null) 61 loginUserNameTemplate.InstantiateIn(this); 62 else 63 base.CreateChildControls(); 64 if(loginUserPasswardTemplate!=null ) 65 loginUserPasswardTemplate .InstantiateIn(this); 66 else 67 base.CreateChildControls(); 68 69 ChildControlsCreated = true; 70 71 72 73 } 74 75 #endregion 76 77 78 79 } 80 81 public class MyLoginDesigner : CompositeControlDesigner 82 { 83 public override void Initialize(IComponent component) 84 { 85 base.Initialize(component); 86 SetViewFlags(ViewFlags.TemplateEditing, true); 87 } 88 89 public override string GetDesignTimeHtml() 90 { 91 TemplateLoginControl control = Component as TemplateLoginControl; 92 if (control != null) 93 { 94 if (control.LoginUserNameTemplate == null) 95 { 96 return CreatePlaceHolderDesignTimeHtml("请您编辑用户名的模板"); 97 98 } 99 100 if (control.LoginUserPasswardTemplate == null) 101 { 102 return CreatePlaceHolderDesignTimeHtml("请您编辑用户密码的模板"); 103 } 104 } 105 return base.GetDesignTimeHtml(); 106 } 107 108 private TemplateGroupCollection tempgc; 109 public override TemplateGroupCollection TemplateGroups 110 { 111 get 112 { 113 if (tempgc == null) 114 { 115 116 tempgc = base.TemplateGroups; 117 118 TemplateGroup loginUserNameTemplate = new TemplateGroup("UserNameTemplate"); 119 loginUserNameTemplate.AddTemplateDefinition (new TemplateDefinition (this,"UserNameTemplate", 120 Component,"UserNameTemplate",false )); 121 tempgc.Add (loginUserNameTemplate ); 122 123 TemplateGroup loginPasswardNameTemplate = new TemplateGroup("UserPasswardTemplate"); 124 loginPasswardNameTemplate.AddTemplateDefinition(new TemplateDefinition(this, "UserPasswardTemplate", 125 Component,"UserPasswardTemplate",false )); 126 tempgc.Add(loginPasswardNameTemplate); 127 } 128 return tempgc; 129 } 130 } 131 } 132} 133 |
























浙公网安备 33010602011771号