asp.net本身提供了很多控件,提供給我們這些比較懶惰的人使用,我認為控件的作用就在此,因為我們不想重復工作,所以要創建它,這個本身便是一個需求的關系,所以學習控件開發很有意思.
wrox網站上有本書
Professional ASP.NET 2.0 Server Control and Component Development
現在還沒有出版,但網站上放出了代碼,所以正好下載過來學習一下.
我看過前幾章代碼,環環相扣,作者用不同的知識向我們展示同一個效果,所以循序漸進的學下來很有好處.
雖然自己對控件開發還不是很熟悉,但我感覺以下幾點很重要,是我自己總結的
1.了解控件之間的繼承關系
最好是先看看看System.Web.UI命名空間
(1)Control 類,所有的控件都共享的一個類,你需要去看下其里面受保護的幾個方法和屬性,雖然一下看不完,以后會發現常常用到這些方法
大家可以在MSDN看一下其派生類
(2)HtmlTextWriter 類
不得不了解的一個類,主要工作就是我們寫的標記字符和文本輸出
2.重寫方法
(1) 必須繼承Control類
(2) 重寫Control類的Render方法,這個是必須的,因為其他控件都繼承了Control 類類,所以幾乎所有控件都有這個方法
3.熟悉元數據
大家都知道asp.net控件屬性在編輯器上是分類的,如外觀,行為,布局等,每個屬性還給出了解釋
簡單的元數據就是起到這個作用,當然你也可以不加,但使用了元數據讓人感到有親切感,寫法如
下
[CategoryAttribute("Appearance")]
要使用元數據,必須引用System.ComponentModel命名控件,一般你如果寫組件的話,不可能不用到這樣類庫。具體的MSDN上有所介紹。
一.輸出字符串
說多了沒意思,還是來演練吧。首先你得了解HTML。來看下面代碼,效果就是輸出HTML到客戶端
示例一
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
using
System;
using
System.Web.UI;
namespace
CustomComponents
{
/**/
///
<summary>
///
SummarydescriptionforCreditCardForm
///
</summary>
public
class
CreditCardForm1:Control
{
protected
override
void
Render(HtmlTextWriterwriter)
{
writer.Write(
"
<tablestyle='width:287px;height:124px;border-width:0;'>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td><strong>PaymentMethod</strong></td>
"
);
writer.Write(
"
<td>
"
);
writer.Write(
"
<selectname='PaymentMethod'id='PaymentMethod'style='width:100%;'>
"
);
writer.Write(
"
<optionvalue='0'>Visa</option>
"
);
writer.Write(
"
<optionvalue='1'>MasterCard</option>
"
);
writer.Write(
"
</select>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td><strong>CreditCardNo.</strong></td>
"
);
writer.Write(
"
<td><inputname='CreditCardNo'id='CreditCardNo'type='text'/></td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td><strong>Cardholder'sName</strong></td>
"
);
writer.Write(
"
<td><inputname='CardholderName'id='CardholderName'type='text'/></td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td><strong>ExpirationDate</strong></td>
"
);
writer.Write(
"
<td>
"
);
writer.Write(
"
<selectname='Month'id='Month'>
"
);
for
(
int
day
=
1
;day
<
13
;day
++
)
{
if
(day
<
10
)
writer.Write(
"
<optionvalue='
"
+
day.ToString()
+
"
'>
"
+
"
0
"
+
day.ToString()
+
"
</option>
"
);
else
writer.Write(
"
<optionvalue='
"
+
day.ToString()
+
"
'>
"
+
day.ToString()
+
"
</option>
"
);
}
writer.Write(
"
</select>
"
);
writer.Write(
"
 
"
);
writer.Write(
"
<selectname='Year'id='Year'>
"
);
for
(
int
year
=
2005
;year
<
2015
;year
++
)
{
writer.Write(
"
<optionvalue='
"
+
year.ToString()
+
"
'>
"
+
year.ToString()
+
"
</option>
"
);
}
writer.Write(
"
</select>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<tdalign='center'colspan='2'>
"
);
writer.Write(
"
<inputtype='submit'value='Submit'/>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
</table>
"
);
base
.Render(writer);
}
}
}
效果很簡單,其實就一直在輸出HTML再加幾個屬性,大家可以直接把代碼放在App_Code文件夾里,就可自動編譯,當然也可以創建web控件庫.
注意要繼承Control類,重寫Render方法,用HtmlTextWriter類的Write輸出HTML
使用控件
(1).需要先注冊一下
<%@ Register TagPrefix="custom" Namespace="CustomComponents" %>
(2) 然后就使用標簽輸出效果
<custom:CreditCardForm1 runat="server" ID="ccf" />
下為效果圖
二.改善,加入屬性和元數據
可能上面做出的 控件毫無用處,但卻可以讓你熟悉一下步驟,上面的控件定的很死,沒有定義任何屬性,用處不大,下面來改造
我們來定義常用屬性,然后再輸出,這樣我們就可以修改控件的屬性了,
示例二
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
using
System;
using
System.Web.UI;
using
System.ComponentModel;
namespace
CustomComponents
{
[DefaultPropertyAttribute(
"
CardholderNameText
"
)]
[ToolboxData(
@"
<{0}:CreditCardForm2
PaymentMethodText='信用卡類型'CreditCardNoText='信用卡卡號'
CardholderNameText='信用卡持有者姓名'SubmitButtonText='提交'
runat='server'></{0}:CreditCardForm2>
"
)
]
public
class
CreditCardForm2:Control
{
private
string
paymentMethodText
=
"
信用卡類型
"
;
private
string
creditCardNoText
=
"
信用卡卡號
"
;
private
string
cardholderNameText
=
"
信用卡持有者姓名
"
;
private
string
expirationDateText
=
"
最后使用時間
"
;
private
string
submitButtonText
=
"
提交
"
;
[BrowsableAttribute(
true
)]
[DescriptionAttribute(
"
獲取和設置信用卡類型
"
)]
[DefaultValueAttribute(
"
信用卡類型
"
)]
[CategoryAttribute(
"
Appearance
"
)]
public
virtual
string
PaymentMethodText
{
get
{
return
this
.paymentMethodText;}
set
{
this
.paymentMethodText
=
value;}
}
[BrowsableAttribute(
true
)]
[DescriptionAttribute(
"
獲取或設置信用卡卡號
"
)]
[DefaultValueAttribute(
"
信用卡卡號
"
)]
[CategoryAttribute(
"
Appearance
"
)]
public
virtual
string
CreditCardNoText
{
get
{
return
this
.creditCardNoText;}
set
{
this
.creditCardNoText
=
value;}
}
[BrowsableAttribute(
true
)]
[DescriptionAttribute(
"
獲取或設置信用卡持有者姓名
"
)]
[DefaultValueAttribute(
"
信用卡持有者姓名
"
)]
[CategoryAttribute(
"
Appearance
"
)]
public
virtual
string
CardholderNameText
{
get
{
return
this
.cardholderNameText;}
set
{
this
.cardholderNameText
=
value;}
}
[BrowsableAttribute(
true
)]
[DescriptionAttribute(
"
獲取或設置最后使用時間
"
)]
[DefaultValueAttribute(
"
最后使用時間
"
)]
[CategoryAttribute(
"
Appearance
"
)]
public
virtual
string
ExpirationDateText
{
get
{
return
this
.expirationDateText;}
set
{
this
.expirationDateText
=
value;}
}
[BrowsableAttribute(
true
)]
[DescriptionAttribute(
"
獲取或設置按鈕標簽
"
)]
[DefaultValueAttribute(
"
提交
"
)]
[CategoryAttribute(
"
Appearance
"
)]
public
virtual
string
SubmitButtonText
{
get
{
return
this
.submitButtonText;}
set
{
this
.submitButtonText
=
value;}
}
protected
override
void
Render(HtmlTextWriterwriter)
{
writer.Write(
"
<tablestyle='width:287px;height:124px;border-width:0;'>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td>
"
+
PaymentMethodText
+
"
</td>
"
);
writer.Write(
"
<td>
"
);
writer.Write(
"
<selectname='PaymentMethod'id='PaymentMethod'style='width:100%;'>
"
);
writer.Write(
"
<optionvalue='0'>Visa</option>
"
);
writer.Write(
"
<optionvalue='1'>MasterCard</option>
"
);
writer.Write(
"
</select>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td>
"
+
CreditCardNoText
+
"
</td>
"
);
writer.Write(
"
<td><inputname='CreditCardNo'id='CreditCardNo'type='text'/></td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td>
"
+
CardholderNameText
+
"
</td>
"
);
writer.Write(
"
<td><inputname='CardholderName'id='CardholderName'type='text'/></td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<td>
"
+
ExpirationDateText
+
"
</td>
"
);
writer.Write(
"
<td>
"
);
writer.Write(
"
<selectname='Month'id='Month'>
"
);
for
(
int
day
=
1
;day
<
13
;day
++
)
{
if
(day
<
10
)
writer.Write(
"
<optionvalue='
"
+
day.ToString()
+
"
'>
"
+
"
0
"
+
day.ToString()
+
"
</option>
"
);
else
writer.Write(
"
<optionvalue='
"
+
day.ToString()
+
"
'>
"
+
day.ToString()
+
"
</option>
"
);
}
writer.Write(
"
</select>
"
);
writer.Write(
"
 
"
);
writer.Write(
"
<selectname='Year'id='Year'>
"
);
for
(
int
year
=
2005
;year
<
2015
;year
++
)
{
writer.Write(
"
<optionvalue='
"
+
year.ToString()
+
"
'>
"
+
year.ToString()
+
"
</option>
"
);
}
writer.Write(
"
</select>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
<tr>
"
);
writer.Write(
"
<tdalign='center'colspan='2'>
"
);
writer.Write(
"
<inputtype='submit'value='
"
+
SubmitButtonText
+
"
'/>
"
);
writer.Write(
"
</td>
"
);
writer.Write(
"
</tr>
"
);
writer.Write(
"
</table>
"
);
base
.Render(writer);
}
}
}
上面我們接觸到了元數據了,意思應該很好理解,為了測試元數據的作用,大家可以新建一個類庫項目,然后把寫的代碼放這個項目里面,接著web網站引用這個項目,成功生成以后,你會發現工具箱已經自動幫你加上了這幾個控件
接著你要做的工作就是拖動你需要的控件,然后你會在屬性面板看到下圖
然后你再結合代碼中的元數據,應該就知道大概意思了.(可以根據你的理解結合MSDN看)
三.再次改善,淘汰用Write方法以字符串的方式輸出HTML
接著我們繼續發現問題,我們發現我們除了定義幾個需要自己來修改的屬性外,還是要用來大量的字符串用來輸出HTML,而且容易輸錯.所以HtmlTextWriter類提供幾個有用的方法用來代替.
(1)AddStyleAttribute方法 為標簽添加樣式屬性
(2)AddAttribute方法 為標簽添加屬性
(3)RenderBeginTag 開始寫入標簽頭 如<table....>
(4)RenderEndTag 寫入標簽尾部,如</table>
這里有幾點需要特別注意.
一.因為其定義方式跟我們平時定義方式不同,我們平時寫HTML時,是先寫標簽開頭,再寫標簽的屬性.如<table borderwidth="0">,然而我們在使用上面幾個方法時,需要有先后順序,
我們需要先定義標簽的屬性和樣式,
然后再輸出標簽頭.
二.標簽頭和尾,需一一對應.可以理解為嵌套關系.最好的理解方法就是輸出代碼后,查看源文件,再結合原來定義的代碼來看.
還是看代碼比較容易說明,由于CreditCardForm2已經定義了我們需要的屬性,而我們現在要做的只是用標簽的形式來替代字符串的形式,所以只需要繼承CreditCardForm2類,重寫Render方法即可
示例三
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
protected
override
void
Render(HtmlTextWriterwriter)
{
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth,
"
0
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(
"
<strong>
"
+
PaymentMethodText
+
"
</strong>
"
);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Name,
"
PaymentMethod
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Id,
"
PaymentMethod
"
);
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
"
100%
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Select);
writer.AddAttribute(HtmlTextWriterAttribute.Value,
"
0
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Option);
writer.Write(
"
Visa
"
);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Value,
"
1
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Option);
writer.Write(
"
MasterCard
"
);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(
"
<strong>
"
+
CreditCardNoText
+
"
</strong>
"
);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Name,
"
CreditCardNo
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Id,
"
CreditCardNo
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Type,
"
text
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(
"
<strong>
"
+
CardholderNameText
+
"
</strong>
"
);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Name,
"
CardholderName
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Id,
"
CardholderName
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Type,
"
text
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(
"
<strong>
"
+
ExpirationDateText
+
"
</strong>
"
);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Name,
"
Month
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Id,
"
Month
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Select);
for
(
int
day
=
1
;day
<
13
;day
++
)
{
writer.AddAttribute(HtmlTextWriterAttribute.Value,day.ToString());
writer.RenderBeginTag(HtmlTextWriterTag.Option);
if
(day
<
10
)
writer.Write(
"
0
"
+
day.ToString());
else
writer.Write(day);
writer.RenderEndTag();
}
writer.RenderEndTag();
writer.Write(
"
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Name,
"
Year
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Id,
"
Year
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Select);
for
(
int
year
=
2005
;year
<
2015
;year
++
)
{
writer.AddAttribute(HtmlTextWriterAttribute.Value,year.ToString());
writer.RenderBeginTag(HtmlTextWriterTag.Option);
writer.Write(year);
writer.RenderEndTag();
}
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Align,
"
center
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Colspan,
"
2
"
);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.AddAttribute(HtmlTextWriterAttribute.Type,
"
submit
"
);
writer.AddAttribute(HtmlTextWriterAttribute.Value,SubmitButtonText);
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
實現的效果雖然一樣,但上面的代碼是不是漂亮很多,而且不容易輸錯.這也是所提倡的做法
四.未使用視圖狀態的后果
還是視圖狀態,關于視圖狀態大家可以參考MSDN和相關文章
看以下的示例,還是CreditCardForm3這個控件
if
(
!
IsPostBack)
{
creditcardform.CardholderNameText
=
"
FullName
"
;
creditcardform.CreditCardNoText
=
"
CreditCardNo
"
;
creditcardform.ExpirationDateText
=
"
ExpirationDate
"
;
creditcardform.PaymentMethodText
=
"
PaymentOptions
"
;
creditcardform.SubmitButtonText
=
"
Send
"
;
}
首次加載效果
點擊按鈕以后
五.使用視圖狀態改善效果
前提條件是你未禁用視圖狀態
繼承CreditCardForm3,改寫每個屬性
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
public
override
string
PaymentMethodText
{
get
{
return
ViewState[
"
PaymentMethodText
"
]
!=
null
?
(
string
)ViewState[
"
PaymentMethodText
"
]:
"
信用卡類型
"
;}
set
{ViewState[
"
PaymentMethodText
"
]
=
value;}
}
public
override
string
CreditCardNoText
{
get
{
return
ViewState[
"
CreditCardNoText
"
]
!=
null
?
(
string
)ViewState[
"
CreditCardNoText
"
]:
"
信用卡卡號
"
;}
set
{ViewState[
"
CreditCardNoText
"
]
=
value;}
}
public
override
string
CardholderNameText
{
get
{
return
ViewState[
"
CardholderNameText
"
]
!=
null
?
(
string
)ViewState[
"
CardholderNameText
"
]:
"
信用卡持有者姓名
"
;}
set
{ViewState[
"
CardholderNameText
"
]
=
value;}
}
public
override
string
ExpirationDateText
{
get
{
return
ViewState[
"
ExpirationDateText
"
]
!=
null
?
(
string
)ViewState[
"
ExpirationDateText
"
]:
"
最后使用時間
"
;}
set
{ViewState[
"
ExpirationDateText
"
]
=
value;}
}
public
override
string
SubmitButtonText
{
get
{
return
ViewState[
"
SubmitButtonText
"
]
!=
null
?
(
string
)ViewState[
"
SubmitButtonText
"
]:
"
提交
"
;}
set
{ViewState[
"
SubmitButtonText
"
]
=
value;}
}
以上全為個人見解,如有錯誤,希望大家指出.
點擊下載代碼
http://www.wrox.com/WileyCDA/WroxTitle/productCd-0471793507.html
asp.net 2.0控件開發
所有相關文章地址:
http://www.cnblogs.com/Clingingboy/category/68883.html?Show=All