http://blog.csdn.net/laodao1/article/details/5897366
ASP.NET自定义控件组件开发
上面显示的是一个输入用户信息的提交控件,如果这个控件很常用,那么我们每次都要这样拖放,那是很累的,为了便于代码重用,就吧它实现为一个控件。
一般来说,自定义控件的都是继承于某一个基类的,不仅如此,我们所用的所有的控件都是继承于一个基类Control类。我们开发控件可以继承任何的服务器控件,如Button,TextBox等等。但是我们一般都继承于三个基类Control,WebControl,CompositeControl,因为这些类给了我们更加灵活的操作。
本章从浅入深,主要讲解继承Control类。
|
62
63 64 65 66 } 67 68 } 69} 70 71 72 |
TOP 好消息!网界网为用户提供免费网络产品测评机会,要测的报名啦!
|
很感谢大家给我的第一篇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>");
}
}
}
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 }
50
51
52
53 }
好了,这写步骤完成之后,工作就差不多完成了。
我想大家应该来记得我们平时用的控件,如下:
例如上面的TextBox控件,他的属性就显示在属性窗口,而且属性都分了类,如”外观“,”行为“,而且没有属性下面都有注释。大家注意途中的标记部分。
我们上面的代码确实已经为控件添加了属性,但是我们要让我们开发的控件和现有的控件一样,看起来更加的专业,我们就要实现一些显示的代码,使得我们的控件和现有的服务器控件一样”好看,好用”。即,要有下面的效果:
这个控件看起来很专业吧!好了,我们来实现下:
其实很简单的,只要添加一些属性(Attribute)标记
[Browsable(true)]//在属性窗口中是否可见
[Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类
[DefaultValue("支付方式")]
[Description("支付方式")]//这些是显示在属性窗口底下的
publicvirtualstringPaymentMethodText
{
get
{
returnpaymentMethod;
}
set
{
paymentMethod=value;
}
}
154
155
156
157 }
158
159 }
160}
161
相信大家看了前几篇文章后应该觉得自定义控件很简单,无非就是把一大堆的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,而且确定他的一些属性等等。如前所说,出错的可能很大,而且兼容也
这段代码和上端代码的最终的显示结果都是一样的(都生成相同的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方法
看个例子:
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 }
变回来了!!!!?????
这里就要讲讲ASP.NET的页面保存值的方式:因为现在的ASP.NET网站是基于http这种无状态协议的。大家应该都懂。
在ASP.NET的我们提交的一个页面,虽然看起来是一样的,但是他们本质上已经不是同一个页面了。而是我们现在看见的页
面获取了之前提交的那个页面的一些状态值。关于这点,到第四章详细讲述”页面的生命周期“中讲。
所有我们就要用个ViewState来保存页面回传的值。这里我不想讲很多的理论东西,大家先看看现在的问题怎样解决:
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