asp.net控件開發基礎(1)

作者: Clingingboy  來源: 博客園  發布時間: 2010-10-02 19:16  閱讀: 1851 次  推薦: 0   原文鏈接   [收藏]  

  asp。net本身提供了很多控件,提供給我們這些比較懶惰的人使用,我認為控件的作用就在此,因為我們不想重復工作,所以要創建它,這個本身便是一個需求的關系,所以學習控件開發很有意思。 wrox網站上有本書 Professional ASPNET 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到客戶端

  示例一

 
using System;
using System.Web.UI;

namespace CustomComponents
{

/// <summary>
/// Summary description for CreditCardForm
/// </summary>
public class CreditCardForm1 : Control
{

protected override void Render(HtmlTextWriter writer)
{
writer.Write(
"<table style='width:287px;height:124px;border-width:0;'>");
writer.Write(
"<tr>");
writer.Write(
"<td><strong>Payment Method</strong></td>");
writer.Write(
"<td>");
writer.Write(
"<select name='PaymentMethod' id='PaymentMethod' style='width:100%;'>");
writer.Write(
"<option value='0'>Visa</option>");
writer.Write(
"<option value='1'>MasterCard</option>");
writer.Write(
"</select>");
writer.Write(
"</td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td><strong>Credit Card No.</strong></td>");
writer.Write(
"<td><input name='CreditCardNo' id='CreditCardNo' type='text' /></td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td><strong>Cardholder's Name</strong></td>");
writer.Write(
"<td><input name='CardholderName' id='CardholderName' type='text' /></td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td><strong>Expiration Date</strong></td>");
writer.Write(
"<td>");
writer.Write(
"<select name='Month' id='Month'>");
for (int day = 1; day < 13; day++)
{

if (day < 10)
writer.Write(
"<option value='" + day.ToString() + "'>" + "0" + day.ToString() + "</option>");
else
writer.Write("<option value='" + day.ToString() + "'>" + day.ToString() + "</option>");
}
writer.Write(
"</select>");
writer.Write(
"&nbsp");
writer.Write(
"<select name='Year' id='Year'>");
for (int year = 2005; year < 2015; year++)
{
writer.Write(
"<option value='" + year.ToString() + "'>" + year.ToString() + "</option>");
}
writer.Write(
"</select>");
writer.Write(
"</td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td align='center' colspan='2'>");
writer.Write(
"<input type='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" />

  下為效果圖

. 改善,加入屬性和元數據

  可能上面做出的 控件毫無用處,但卻可以讓你熟悉一下步驟,上面的控件定的很死,沒有定義任何屬性,用處不大,下面來改造我們來定義常用屬性,然后再輸出,這樣我們就可以修改控件的屬性了,

示例二

 

 
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(HtmlTextWriter writer)
{
writer.Write(
"<table style='width:287px;height:124px;border-width:0;'>");
writer.Write(
"<tr>");
writer.Write(
"<td>" + PaymentMethodText + "</td>");
writer.Write(
"<td>");
writer.Write(
"<select name='PaymentMethod' id='PaymentMethod' style='width:100%;'>");
writer.Write(
"<option value='0'>Visa</option>");
writer.Write(
"<option value='1'>MasterCard</option>");
writer.Write(
"</select>");
writer.Write(
"</td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td>" + CreditCardNoText + "</td>");
writer.Write(
"<td><input name='CreditCardNo' id='CreditCardNo' type='text' /></td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td>" + CardholderNameText + "</td>");
writer.Write(
"<td><input name='CardholderName' id='CardholderName' type='text' /></td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td>" + ExpirationDateText + "</td>");
writer.Write(
"<td>");
writer.Write(
"<select name='Month' id='Month'>");
for (int day = 1; day < 13; day++)
{

if (day < 10)
writer.Write(
"<option value='" + day.ToString() + "'>" + "0" + day.ToString() + "</option>");
else
writer.Write("<option value='" + day.ToString() + "'>" + day.ToString() + "</option>");
}
writer.Write(
"</select>");
writer.Write(
"&nbsp");
writer.Write(
"<select name='Year' id='Year'>");
for (int year = 2005; year < 2015; year++)
{
writer.Write(
"<option value='" + year.ToString() + "'>" + year.ToString() + "</option>");
}
writer.Write(
"</select>");
writer.Write(
"</td>");
writer.Write(
"</tr>");
writer.Write(
"<tr>");
writer.Write(
"<td align='center' colspan='2'>");
writer.Write(
"<input type='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方法即可

  示例三

 

 
protected override void Render(HtmlTextWriter writer)
{
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(
"&nbsp;");

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 = "Full Name";
      creditcardform
CreditCardNoText = "CreditCardNo";
      creditcardform
ExpirationDateText = "ExpirationDate";
      creditcardform
PaymentMethodText = "Payment Options";
      creditcardform
SubmitButtonText = "Send";
    }

  首次加載效果

  點擊按鈕以后

使用視圖狀態改善效果

  前提條件是你未禁用視圖狀態,繼承CreditCardForm3,改寫每個屬性

 

 
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; }
}

  以上全為個人見解,如有錯誤,希望大家指出。

下一篇:asp.net控件開發基礎(2)

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()