日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

詳細(xì)闡述利用ASP.NET 2.0創(chuàng)建自定義Web控件開(kāi)發(fā)

系統(tǒng) 2176 0
簡(jiǎn)介

  從使用基本的文本編輯器到創(chuàng)作標(biāo)記頁(yè)面,Web 開(kāi)發(fā)已經(jīng)經(jīng)歷了一個(gè)漫長(zhǎng)的過(guò)程。目前,集成開(kāi)發(fā)環(huán)境 (IDE) 為開(kāi)發(fā)過(guò)程中的幾乎每個(gè)方面都提供了圖形化表示形式。此外,還實(shí)現(xiàn)各種說(shuō)明性 編程 技術(shù)以提高效率并降低出現(xiàn)錯(cuò)誤的幾率。Visual Studio 2005 和 ASP .NET 2.0 中的控件體系結(jié)構(gòu)遵循了這些編程趨勢(shì),并且提供了可靠的、可擴(kuò)展的環(huán)境,該環(huán)境 設(shè)計(jì) 為使開(kāi)發(fā)人員可以創(chuàng)建能夠以說(shuō)明方式配置的控件。

  此外,ASP.NET 中新的自適應(yīng)呈現(xiàn)模型減少了編寫(xiě)可專(zhuān)門(mén)識(shí)別其目標(biāo)瀏覽器的控件的需要。換句話(huà)說(shuō),控件開(kāi)發(fā)人員可以專(zhuān)注于設(shè)計(jì)控件,而讓 ASP.NET 框架負(fù)責(zé)轉(zhuǎn)換控件并針對(duì)不同類(lèi)型的瀏覽器和設(shè)備呈現(xiàn)它。

  盡管 ASP.NET 2.0 在控件設(shè)計(jì)過(guò)程中提供了增量改進(jìn)功能,但實(shí)際控件呈現(xiàn)模型已經(jīng)完全進(jìn)行了更改。作為自定義控件開(kāi)發(fā)人員,您將會(huì)看到利用 ASP.NET 的幾個(gè)新選項(xiàng)。最重要的是,您將會(huì)發(fā)現(xiàn)只需編寫(xiě)較少的代碼便可完成相同的任務(wù)。

  在 ASP.NET 2.0 中,創(chuàng)建自定義服務(wù)器控件有很多方法,每種方法都有其優(yōu)點(diǎn)和局限性。本文將討論與自定義控件的創(chuàng)建和配置相關(guān)的詳細(xì)信息。代碼示例和體系結(jié)構(gòu)概念要求您對(duì) C# 編程語(yǔ)言具有中等水平的理解。

自適應(yīng)呈現(xiàn)模型

  在 ASP.NET 1.x 中,自定義控件開(kāi)發(fā)人員必須設(shè)計(jì)每個(gè)服務(wù)器控件,以便它可以識(shí)別不同的瀏覽器類(lèi)型并發(fā)出正確的輸出。ASP.NET 1.x 控件框架提供了幾項(xiàng)功能以使該任務(wù)變得更簡(jiǎn)單,但開(kāi)發(fā)人員仍然必須根據(jù)瀏覽器的類(lèi)型編寫(xiě)切換程序、開(kāi)發(fā)適當(dāng)?shù)? HTML ,然后針對(duì)不同類(lèi)型的瀏覽器測(cè)試控件。此外,如果開(kāi)發(fā)人員希望控件在移動(dòng)設(shè)備上顯示,他必須創(chuàng)建一個(gè)與普通 Web 瀏覽器上使用的控件不同的全新控件。

  ASP.NET 2.0 通過(guò)新的自適應(yīng)呈現(xiàn)模型簡(jiǎn)化了瀏覽器檢測(cè)和呈現(xiàn)過(guò)程。在 ASP.NET 2.0 中引入的自適應(yīng)呈現(xiàn)模型旨在用于支持那些眾多能夠使用標(biāo)記格式(包括 HTML、WML、XHTML 或 CHMTL)的不同設(shè)備。

自適應(yīng)呈現(xiàn)模型體系結(jié)構(gòu)

  每個(gè)控件都可以鏈接到一個(gè)適配器,它會(huì)針對(duì)特定的目標(biāo)設(shè)備修改控件的行為和標(biāo)記。例如,HTML 適配器將 ASP.NET 控件生成為標(biāo)準(zhǔn)的 HTML 和 DHTML,以便普通 Web 瀏覽器使用。另一方面,WML 適配器將相同的控件轉(zhuǎn)換成 無(wú)線(xiàn) 標(biāo)記語(yǔ)言,以便蜂窩電話(huà)或其他移動(dòng)設(shè)備使用。


圖 1. 控件-適配器壽命周期


  上圖說(shuō)明了控件方法與適配器方法之間一對(duì)一的映射。如果有適配器(如果控件的 Adapter 屬性不為空),執(zhí)行就會(huì)在控件和適配器方法之間傳輸,如上圖所示。在生成階段,控件對(duì)象或適配器對(duì)象都可以生成輸出(通常情況下兩者不同時(shí)生成輸出)。通常情況下,如果有適配器,那么適配器的實(shí)現(xiàn)將覆蓋控件的實(shí)現(xiàn)。在 ASP.NET 2.0 中,自適應(yīng)呈現(xiàn)模型適用于所有 ASP.NET 控件(不僅僅是移動(dòng)控件),并且允許 ASP.NET 2.0 支持統(tǒng)一的控件體系結(jié)構(gòu)。



實(shí)際意義

  自適應(yīng)呈現(xiàn)模型的實(shí)際意義有兩個(gè)主要方面。第一,作為開(kāi)發(fā)人員,您可以一次設(shè)計(jì)控件并期望它可以在具有適配器的任何類(lèi)型的設(shè)備或?yàn)g覽器上使用。第二,您可以對(duì)常用適配器利用廣泛的 Microsoft 測(cè)試,減少您自己瀏覽器的特定測(cè)試。

  自適應(yīng)呈現(xiàn)模型還為 ASP.NET 2.0 提供了將其他服務(wù)添加到控件生成過(guò)程中的機(jī)會(huì)。由于具有適配器模型,您可以:

  1) 根據(jù)目標(biāo)的類(lèi)型,使用篩選器 來(lái)更改控件的外觀。

  2) 根據(jù)目標(biāo)的類(lèi)型,使用模板來(lái)更改整個(gè)頁(yè)面布局。

  3) 根據(jù)瀏覽器控制在瀏覽器上的呈現(xiàn),而不必依賴(lài)于 ASP.NET 1.x 的 uplevel/downlevel 確定。

  在本文中,我們將重點(diǎn)放在創(chuàng)建自定義控件的應(yīng)用方面。但是,請(qǐng)牢記自適應(yīng)呈現(xiàn)模型是新的基礎(chǔ)框架。

創(chuàng)建自定義服務(wù)器控件

  Visual Studio 2005 提供了很多用于開(kāi)發(fā)自定義服務(wù)器控件的有用工具。為了說(shuō)明某些功能,我們將創(chuàng)建一個(gè) MailLink 控件,它公開(kāi)了兩個(gè)屬性:Email 和 Text。該控件將生成必需的 HTML 來(lái)將所提供的 Text 包裝到 mailto: 鏈接標(biāo)記中。


創(chuàng)建項(xiàng)目

  在 Visual Studio 2005 中,我們通過(guò)在新建項(xiàng)目向?qū)е羞x擇適當(dāng)?shù)膱D標(biāo)來(lái)創(chuàng)建一個(gè)新的“Web Control Library”項(xiàng)目:


圖 2. Visual Studio 2005 中的新建項(xiàng)目向?qū)?


  該項(xiàng)目是利用默認(rèn)的自定義控件類(lèi)實(shí)現(xiàn)創(chuàng)建的。對(duì)于我們的示例,我們將該默認(rèn)文件重命名為 MailLink.cs。

  注:在解決方案資源管理器中重命名該文件時(shí),Visual Studio 2005 將會(huì)自動(dòng)更新類(lèi)名。

  MailLink 的源代碼在由項(xiàng)目向?qū)傻哪J(rèn)模板上構(gòu)建。MailLink 類(lèi)從 WebControl 基類(lèi)自動(dòng)派生。

public class MailLink : WebControl {


  WebControl 類(lèi)提供默認(rèn)實(shí)現(xiàn)方法,可以很簡(jiǎn)單地覆蓋這些方法來(lái)為我們的控件提供詳細(xì)說(shuō)明。

添加屬性

  在 MailLink 示例中,我們需要添加 Email 和 Text 屬性。為了正確配置這些屬性,我們不僅必須編寫(xiě)代碼,還要分配幾個(gè)特性。

[Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The e-mail address.")]

public virtual string Email {
get {
string s = (string)ViewState["Email"];
return (s == null) ? String.Empty : s;
}
set {
ViewState["Email"] = value;
}
}


  特性(以粗體表示)定義了新控件將如何與 設(shè)計(jì) 器 (Visual Studio) 進(jìn)行交互。Email 屬性的特性告訴 Visual Studio 如何在設(shè)計(jì)過(guò)程中處理屬性:

  1) Bindable — Email 屬性可綁定 到數(shù)據(jù)源。您可以將 Email 字段鏈接到 數(shù)據(jù)庫(kù) XML 文件或任何其他 DataSet。該特性強(qiáng)制 Visual Studio 在控件的可綁定屬性列表中顯示 Email 屬性。

  2) Appearance —Email 屬性將顯示在 Appearance 類(lèi)別下的屬性視圖中。您可以選擇想要的任何類(lèi)別,包括默認(rèn)類(lèi)別:Appearance、 Access ibility、Behavior、Data、Layout 或 Misc。只要用戶(hù)選擇了屬性的類(lèi)別組織方法,Email 屬性將會(huì)顯示在 Appearance 下。

  3) DefaultValue — Email 屬性具有一個(gè)空的默認(rèn)值。盡管空值對(duì)于 Email 字段來(lái)說(shuō)有意義,但對(duì)于您添加到控件中的其他屬性可能并不合適。當(dāng)用戶(hù)將您的控件放到他們的 Web 頁(yè)上時(shí),選擇適當(dāng)?shù)哪J(rèn)值可為用戶(hù)免去不計(jì)其數(shù)的單擊操作。

  4) Description — 屬性說(shuō)明顯示在控件列表下,并且也可能作為工具提示出現(xiàn)。Email 屬性將具有 The e-mail address 說(shuō)明。

  5) Localizable — 它會(huì)用發(fā)送信號(hào)的方式通知 ASP.NET 2.0 Framework 該控件包括可以針對(duì)不同語(yǔ)言或位置進(jìn)行配置的文本屬性。

  您可以使用 System.ComponentModel 命名空間中的各種特性來(lái)進(jìn)一步改進(jìn)任何特殊屬性的外觀和行為。我們將在本文的使用設(shè)計(jì)器部分中更詳細(xì)地介紹修改屬性或控件的行為的方法。

  接下來(lái),我們需要添加 Text 屬性。Text 屬性與 Email 屬性稍有不同,因?yàn)槲覀兿M麑?Text 顯示為由 MailLink 控件發(fā)出的 HTML 的一部分。為此,我們需要從 System.Web.UI 命名空間中添加一個(gè)新的特性。

[Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display on the link."),
Localizable(true),
PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public virtual string Text {
get {
string s = (string)ViewState["Text"];
return (s == null) ? String.Empty : s;
}
Set {
ViewState["Text"] = value;
}
}


  Text 屬性的 PersistenceMode(PersistenceMode.InnerDefaultProperty) 特性(粗體代碼)指定設(shè)計(jì)器應(yīng)該將該屬性作為控件標(biāo)記內(nèi)的內(nèi)部?jī)?nèi)容序列化。該特性還聲明 Text 是控件的默認(rèn)屬性。當(dāng)用戶(hù)在 Visual Studio 中使用這個(gè)控件時(shí),Text 屬性將會(huì)作為該控件的內(nèi)部文本自動(dòng)顯示在圖形設(shè)計(jì)器上,并且如果用戶(hù)單擊該控件并嘗試更改顯示的文本,Text 屬性將會(huì)自動(dòng)更改。

  另一方面,應(yīng)用到屬性的特性會(huì)影響設(shè)計(jì)期間用戶(hù)與控件的交互方式。在運(yùn)行過(guò)程中,這些特性被 ASP .NET 運(yùn)行時(shí)忽略。 有關(guān) ViewState 的注釋

  請(qǐng)注意,用于兩個(gè)屬性的 Get 和 Set 方法都利用 ViewState 對(duì)象。ViewState 對(duì)象是一個(gè)內(nèi)置到 WebControl 類(lèi)中的幫助器對(duì)象。從開(kāi)發(fā)角度講,ViewState 可被視為一個(gè)集合類(lèi),用于存儲(chǔ)在回發(fā)過(guò)程中我們想要保留的任意屬性。實(shí)際上,ViewState 封裝了確定如何執(zhí)行持久性(使用 Cookie、會(huì)話(huà)等等)所需的所有代碼和邏輯。

生成控件

  在定義了控件屬性之后,接下來(lái)的步驟就是要 設(shè)計(jì) 將由控件發(fā)出的實(shí)際響應(yīng)。在 MailLink 示例中,我們希望設(shè)計(jì)控件來(lái)生成基本的 HTML 標(biāo)記。

TagKey

  WebControl 的默認(rèn)實(shí)現(xiàn)會(huì)生成一個(gè) 標(biāo)記。我們的 MailLink 控件通過(guò)為 TagKey 屬性提供它自己的實(shí)現(xiàn)來(lái)覆蓋該默認(rèn)實(shí)現(xiàn)。TagKey 屬性定義將要封裝控件內(nèi)容的最外面的標(biāo)記。

  幸運(yùn)的是,我們可以使用 HtmlTextWriterTag 枚舉來(lái)指示鏈接 標(biāo)記,而不必實(shí)際編寫(xiě) HTML 文本。該枚舉方法用于最常用的 HTML 標(biāo)記。

protected override HtmlTextWriterTag TagKey {
get {
return HtmlTextWriterTag.A;
}
}


  如果您需要生成一個(gè)不屬于 HtmlTextWriterTag 枚舉的一部分的標(biāo)記,您必須覆蓋 WebControl.TagName 屬性,而非 TagKey 屬性。TagName 屬性會(huì)返回由控件生成的實(shí)際 HTML 標(biāo)記字符串。TagName 的默認(rèn) WebControl 實(shí)現(xiàn)只調(diào)用 TagKey,并以完美的提取方式提取正確的 HTML。

AttributesToRender

  在定義了基本標(biāo)記之后,接下來(lái)的步驟就是分配我們要添加到該標(biāo)記中的各種特性。我們的 MailLink 控件將覆蓋 AddAttibutesToRender 方法以便為“mailto”標(biāo)記添加適當(dāng)?shù)臉?biāo)記。

protected override void AddAttributesToRender(
HtmlTextWriter writer){
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Href,
"mailto:" + Email);
}


  對(duì)基類(lèi)的 addAtributeToRender() 調(diào)用會(huì)被調(diào)用,以確保可以正確生成其他樣式和特性。如果我們忽略該基本調(diào)用,我們可能會(huì)失去內(nèi)置到所有 Web 控件中的母版頁(yè)設(shè)計(jì)、篩選器或其他功能。

RenderContents

  最后,由于所需的 WebControl 類(lèi)的方法和屬性都已被覆蓋,因此可以使用 RenderContents 方法來(lái)編寫(xiě)文本。出于 安全 原因,MailLink 使用 HtmlTextWriter.WriteEncodedText 方法編寫(xiě) HTML 編碼輸出。HTML 編碼安全地將潛在的危險(xiǎn)字符轉(zhuǎn)換為更安全的表示形式。

protected override void RenderContents(
 HtmlTextWriter writer) {
  if (Text == String.Empty) {
   Text = Email;
  }
  writer.WriteEncodedText(Text);
}


  請(qǐng)注意,我們只生成 Text 屬性。如果 Text 屬性為空,我們將利用 Email 屬性填充它。請(qǐng)記住,Text 屬性旨在用作控件標(biāo)記的內(nèi)部文本。這種類(lèi)型的控件至少需要某一可顯示的文本(以便用戶(hù)進(jìn)行單擊)。如果我們?cè)噲D生成一個(gè)空字符串,我們將失去鏈接標(biāo)記的預(yù)期功能。

如何生成的?

  Render() 方法基本上控制著 WebControl 的整個(gè)輸出。默認(rèn)情況下,Render() 方法實(shí)際上會(huì)依次調(diào)用 RenderBeginTag()、RenderContents() 以及 RenderEndTag()。盡管在 ASP.NET 1.x 中調(diào)用結(jié)構(gòu)并未變化,但由于該呈現(xiàn)模型,修改這些調(diào)用的影響卻發(fā)生了變化。

  您可以覆蓋 Render() 方法來(lái)發(fā)出您想要的任何內(nèi)容。換句話(huà)說(shuō),您可能已經(jīng)跳過(guò)了覆蓋 TagKey 屬性、AttributestoRender 屬性和 RenderContents() 方法,并且僅使 Render() 編寫(xiě)“text”。但是,這種做法可能會(huì)嚴(yán)重影響自適應(yīng)呈現(xiàn)。如果重寫(xiě) Render() 來(lái)直接發(fā)出最終輸出,您會(huì)繞過(guò)內(nèi)置到 WebControl 類(lèi)中的大多數(shù)自適應(yīng)呈現(xiàn)特性。

  自適應(yīng)呈現(xiàn)模型和各種適配器的作用是:截獲對(duì)各種標(biāo)記方法的調(diào)用并轉(zhuǎn)換特定設(shè)備的輸出。在 MailLink 的特定示例中,幾乎所有的標(biāo)記語(yǔ)言都支持用于 鏈接的相同語(yǔ)法。但是,其他標(biāo)記通常在不同的標(biāo)記語(yǔ)言中會(huì)有截然不同的轉(zhuǎn)換。如果我們?yōu)檫@樣的標(biāo)記使用了 Render(),我們的控件將只能在某些瀏覽器上使用,而適配器無(wú)法更改該行為。通過(guò)設(shè)計(jì)控件以使用自適應(yīng)元素而不是使用 Render(),您可以讓 ASP .NET 框架有機(jī)會(huì)根據(jù)瀏覽器提供在瀏覽器上的呈現(xiàn)服務(wù)。

使用自定義控件

  自定義控件能夠以很多方法包括在 Web 應(yīng)用程序中。標(biāo)準(zhǔn)方法是將自定義控件編譯到一個(gè)程序集中,然后在使用該控件的所有 Web 應(yīng)用程序中添加一個(gè)對(duì)該程序集的引用。

使用 EmailLink

  為了使用 EmailLink 控件,您需要:

  1.將 MyControls 項(xiàng)目編譯到一個(gè)程序集中。


圖 3. 編譯包含 EmailLink 控件的 MyControls 命名空間


  2.在新的 Web 項(xiàng)目中添加一個(gè)對(duì)已編譯程序集的引用。


圖 4. 編譯應(yīng)用程序并添加一個(gè)引用


  在正確添加引用之后,自定義控件應(yīng)該出現(xiàn)在工具箱中的“MyControls Components”下。


圖 5. 工具箱中的 EmailLink


  MyControls 程序集中的所有組件都使用默認(rèn)的齒輪圖標(biāo),因?yàn)槲覀兾丛诿總€(gè)控件上設(shè)置特定的圖標(biāo)。設(shè)置圖標(biāo)如同在該控件類(lèi)上調(diào)整圖標(biāo)屬性那樣簡(jiǎn)單。


頁(yè)面上的控件

  在添加了對(duì)包含控件的程序集的引用之后,您可以將 MailLink 控件拖動(dòng)到 設(shè)計(jì) 器表面并像使用任何其他 ASP.NET 服務(wù)器控件那樣使用它。


圖 6. MailLink 自定義控件


  圖 6 展示了 MailLink 控件的設(shè)計(jì)器視圖。請(qǐng)注意,Properties 窗口公開(kāi)了預(yù)期的 Email 和 Text 元素,它們可以用于配置控件。通過(guò)將自定義控件編譯到可重復(fù)使用的程序集中,MailLink 控件可以被很多 Web 應(yīng)用程序重復(fù)使用。

創(chuàng)建復(fù)合服務(wù)器控件

  諸如 Login 和 GridView 這些可靠的控件是由很多基本控件組成的。在 ASP .NET 1.x 中,您必須通過(guò)艱苦的工作將嵌套標(biāo)記和元素添加到自定義控件中來(lái)開(kāi)發(fā)復(fù)合控件。在 ASP.NET 2.0 中,您可以通過(guò)擴(kuò)展 System.Web.UI.WebControls.CompositeControl 類(lèi)來(lái)構(gòu)建復(fù)雜的復(fù)合控件。CompositeControl 類(lèi)提供了將多個(gè)控件的輸出合并到單個(gè)統(tǒng)一的控件中所必需的框架。

  管理復(fù)合控件比管理基本自定義控件稍微困難一些,因?yàn)閺?fù)合控件需要一些自定義布局的信息。復(fù)合控件將它們的呈現(xiàn)和事件處理任務(wù)委托給構(gòu)成控件。子組件的所有關(guān)聯(lián)的適配器類(lèi)也會(huì)被自動(dòng)應(yīng)用。這樣,如果您具有適當(dāng)?shù)倪m配器,復(fù)合控件將會(huì)在任何目標(biāo)瀏覽器類(lèi)型或設(shè)備上正確地呈現(xiàn)。

創(chuàng)建復(fù)合控件

  創(chuàng)建復(fù)合控件的初始過(guò)程與創(chuàng)建自定義服務(wù)器控件的初始過(guò)程相似。但是,該過(guò)程還涉及了更多的步驟。在以下示例中,我們將創(chuàng)建一個(gè)由 Label 和 TextBox 組成的簡(jiǎn)單的復(fù)合 AgeCollector 控件,它旨在收集生日的信息。

  復(fù)合控件類(lèi)應(yīng)該通過(guò)從 CompositeControl 繼承開(kāi)始。

public class AgeCollector : CompositeControl{}


定義屬性

  對(duì)于我們的簡(jiǎn)單控件,我們必須為標(biāo)簽 (Prompt) 和文本框 (DateOfBirth) 創(chuàng)建屬性。

[Bindable(true), Category("Appearance"),
DefaultValue("Please enter your date of birth:"),
Description("Text to prompt user with.")
Localizable(true)]
public virtual String Prompt {
 get
 {
  string s = (string)ViewState["Prompt"];
  return (s == null) ? String.Empty : s;
 }
 set {
  ViewState["Prompt"] = value;
 }
}


  再一次,我們使用特性為屬性提供說(shuō)明和默認(rèn)值。我們選擇了使提示可以進(jìn)行本地化,以便該控件無(wú)論何時(shí)都可以用于要求進(jìn)行國(guó)際化的應(yīng)用程序中。實(shí)際的提示可以綁定到包含語(yǔ)言特定文本的資源文件。

  還必須定義 DateOfBirth 屬性。但是,我們不是使用 String,而是使用 DateTime 數(shù)據(jù)類(lèi)型來(lái)正確地存儲(chǔ)日期。

[Bindable(true), Category("Appearance"),
DefaultValue(""),
Description("Date of Birth Input area")]
public virtual DateTime DateOfBirth {
 get
 {
  bject o = ViewState["DateOfBirth"];
  return (o == null) ? DateTime.Now : (DateTime)o;
 }
 set {
  ViewState["DateOfBirth"] = value;
 }
}


  CreateChildControls 方法

我們的復(fù)合控件由一個(gè)標(biāo)簽和一個(gè)文本框組成。我們無(wú)法使用簡(jiǎn)單控件的技術(shù)來(lái)顯示這兩個(gè)標(biāo)記,除非使用強(qiáng)制方式和 Render() 方法。因?yàn)槲覀兿M米赃m應(yīng)呈現(xiàn)并顯示我們的兩個(gè)控件,所以我們需要覆蓋內(nèi)置到 CompositeControl 類(lèi)中的 CreateChildControls() 方法。這種方法使我們可以定義控件,并將我們的復(fù)合控件的屬性傳遞到要顯示的單個(gè)控件中。

protected override void CreateChildControls() {
 //Create and load the label
 Label lab1 = new Label();
 lab1.Text = Prompt;
 lab1.ForeColor = this.ForeColor;
 this.Controls.Add(lab1);

 //Add a line break between the label and text box
 Literal lit = new Literal();
 lit.Text = "";
 this.Controls.Add(lit);

 //Add the Textbox
 TextBox tb = new TextBox();
 tb.ID = "tb1";
 tb.Text = DateOfBirth.ToString();
 this.Controls.Add(tb);

 //call the parent method
 base.CreateChildControls();
}

  請(qǐng)注意,我們必須初始化每個(gè)控件、分配所有屬性,然后將控件添加到內(nèi)置到 CompositeControl 類(lèi)中的 Controls 集合。我們還使用了 Literal 對(duì)象將換行符置于標(biāo)簽和控件之間。Literal 對(duì)象是非常簡(jiǎn)單的控件,您可以使用它在功能元素之間插入原始 HTML

  請(qǐng)注意,我們還對(duì)基本方法進(jìn)行了調(diào)用,以便確保我們的復(fù)合控件具有內(nèi)置到 CompositeControl 基類(lèi)中的任何其他功能。尤其是,基本方法會(huì)強(qiáng)制 ASP.NET 將 Controls 集合的所有元素添加到控件樹(shù)中。如果我們忽略這個(gè)調(diào)用,或者將其置于我們方法的頂部,那么復(fù)合控件將不會(huì)正確地生成。

完整的 AgeCollector

  當(dāng)我們的 AgeCollector 控件生成時(shí), ASP .NET 將在每個(gè)子控件上實(shí)際調(diào)用適當(dāng)?shù)姆椒ǎ⒔Y(jié)果合并到復(fù)合控件的輸出中。換句話(huà)說(shuō),如果我們已正確地 設(shè)計(jì) 了簡(jiǎn)單控件,那么該復(fù)合控件就只是一個(gè)容器。自適應(yīng)呈現(xiàn)模型將會(huì)自動(dòng)應(yīng)用到每個(gè)子控件中。但是,實(shí)際的 CompositeControl 將不會(huì)被修改,因?yàn)樗话枰牡娜魏慰丶?

  以下是另一個(gè)實(shí)例,其中使用的適當(dāng)方法 (CreateChildControls()) 利用了自適應(yīng)呈現(xiàn)模型,而不是簡(jiǎn)單地在 WebControl 上重載 Render() 方法。由于自適應(yīng)呈現(xiàn)模型和 CompositeControl 的特性,ASP.NET 2.0 節(jié)省了我們的開(kāi)發(fā)時(shí)間、減少了代碼行數(shù)并減少了很多的測(cè)試煩惱。只要我們知道元素控件可通過(guò)特定適配器正確地生成,CompositeControl 將會(huì)通過(guò)該適配器正確地生成。

  如果我們將控件拖動(dòng)到 ASP.NET 頁(yè)面上并查看屬性,我們將會(huì)看到具有 Prompt 和 DateOfBirth 屬性的單個(gè)控件。


圖 7. AgeCollector 使用

  請(qǐng)注意,如果我們將復(fù)合控件的 ForeColor 更改為紅色,我們實(shí)際上更改了 Label 的 ForeColor。但是,我們尚未鏈接某些其他屬性。例如,我們無(wú)法更改 DateOfBirth 字段的 ForeColor。換句話(huà)說(shuō),當(dāng)您構(gòu)建一個(gè)復(fù)合控件時(shí),您始終需要考慮應(yīng)該公開(kāi)哪些子控件屬性。



添加控件行為

  到目前為止,我們?cè)O(shè)計(jì)的兩個(gè)控件都是簡(jiǎn)單、靜態(tài)的控件。也就是說(shuō),這些控件不會(huì)完成利用普通的內(nèi)置控件或簡(jiǎn)單用戶(hù)控件 (.ascx) 無(wú)法完成的任何操作。構(gòu)建自定義服務(wù)器控件的主要原因之一就是要提供使用現(xiàn)有控件集無(wú)法執(zhí)行的新功能。

事件模型

  在 Web 窗體頁(yè)面中,與服務(wù)器控件關(guān)聯(lián)的事件由客戶(hù)端引發(fā)并由 Web 服務(wù)器處理。對(duì)于在客戶(hù)機(jī)上由服務(wù)器控件引發(fā)的事件,ASP.NET 2.0 事件模型收集有關(guān)請(qǐng)求的信息,并使用 HTTP Post 將詳細(xì)信息傳遞到服務(wù)器。服務(wù)器上的 Page Framework 對(duì)該公告作出解釋以確定發(fā)生的事件,然后調(diào)用適當(dāng)?shù)奶幚沓绦蚍椒ā?


圖 8. 典型的服務(wù)器控件事件

  ASP.NET 2.0 可處理幾乎所有捕獲、傳輸和解釋事件的方法。詳細(xì)信息對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)是隱藏的,開(kāi)發(fā)人員只需要關(guān)心服務(wù)器上的處理程序方法的實(shí)現(xiàn)。

 大多數(shù)服務(wù)器事件要求一個(gè)到服務(wù)器的往返以便進(jìn)行處理,因此支持有限數(shù)量的單擊類(lèi)型事件。出于性能原因,不支持鼠標(biāo)懸停和其他內(nèi)部事件。

回發(fā)事件

ASP.NET 2.0 中的很多服務(wù)器控件都生成回發(fā)事件。回發(fā)事件將頁(yè)面?zhèn)鬟f到服務(wù)器以便進(jìn)行處理。這是一個(gè)非常昂貴的操作,因?yàn)樗箜?yè)面通過(guò)網(wǎng)絡(luò)進(jìn)行傳遞。

  回發(fā)模型自從 ASP .NET 1.x 就沒(méi)有進(jìn)行過(guò)顯著更改。為了創(chuàng)建一個(gè)可處理回發(fā)的控件,您的控件必須實(shí)現(xiàn) IPostBackDataHandler 接口,它定義了兩個(gè)方法:

  1) LoadPostData — 該方法處理您控件的回發(fā)數(shù)據(jù)。

  2) RaisePostDataChangedEvent — 該事件通知應(yīng)用程序由于處理回發(fā)數(shù)據(jù),該控件的狀態(tài)已經(jīng)更改。

  PostDataChangedEvent 調(diào)用引發(fā)的事件必須在該控件內(nèi)部定義。然后,用戶(hù)可以在開(kāi)發(fā)過(guò)程中編寫(xiě)實(shí)際的事件方法。

非回發(fā)事件

  某些服務(wù)器控件支持非回發(fā)事件。此類(lèi)事件會(huì)更改控件的狀態(tài),但并不要求立即進(jìn)行處理。這些事件由控件緩存,而不是立即傳遞到服務(wù)器以進(jìn)行處理。例如,ListBox 控件可能包含很多元素。如果用戶(hù)選擇一個(gè)不同的元素,那么控件將在不通知服務(wù)器的情況下顯示適當(dāng)?shù)母牟⒂涀∑湫聽(tīng)顟B(tài)。在張貼包含 ListBox 的窗體之后,ListBox 控件將提交事件(選定的項(xiàng))。

  非回發(fā)事件的默認(rèn)行為可以通過(guò)設(shè)置 AutoPostBack 屬性進(jìn)行更改。如果 AutoPostBack 設(shè)置為 true,那么通常由客戶(hù)端緩存的事件發(fā)送信號(hào)通知服務(wù)器立即進(jìn)行處理。啟用 AutoPostBack 的控件要求客戶(hù)機(jī)允許運(yùn)行腳本。

  ASP.NET 2.0 并未以任何明顯的方式更改該模型。

回調(diào)和帶外請(qǐng)求

  標(biāo)準(zhǔn)的 Web 協(xié)議 設(shè)計(jì) 用于同步通訊。每個(gè)請(qǐng)求接收響應(yīng)的速度與服務(wù)器生成數(shù)據(jù)的速度同樣快。但是,很多任務(wù)都需要帶外 請(qǐng)求,例如同一時(shí)間訪(fǎng)問(wèn)第三方資源。這些請(qǐng)求未處于瀏覽器和 Web 服務(wù)器之間的標(biāo)準(zhǔn)通訊帶區(qū)內(nèi),因此被認(rèn)為是帶外請(qǐng)求。

ASP.NET 1.x 中的帶外

  進(jìn)行帶外數(shù)據(jù)請(qǐng)求的要求提示眾多開(kāi)發(fā)人員可以創(chuàng)造性地使用可用資源來(lái)獲得所需的功能。例如,通過(guò)使用 ActiveX 組件和 JavaScript ,開(kāi)發(fā)人員能夠進(jìn)行外部 HTTP 調(diào)用而無(wú)需完全回發(fā)到服務(wù)器。下面的 Java Script 示例說(shuō)明了可以與 ASP.NET 1.x 一起使用的帶外 HTTP 請(qǐng)求。

function RetrieveGoogle FrontPage () {
 var XmlHttp = new ActiveXObject("Msxml2. XML HTTP.4.0");
 XmlHttp.Open("GET", "http://www.fakedomain.com", false);
 XmlHttp.Send();
 return XmlHttp.responseText;
}

  這種機(jī)制的一個(gè)缺點(diǎn)就是 XmlHttp.responseText 包含該請(qǐng)求的完整結(jié)果。開(kāi)發(fā)人員將必須編寫(xiě)只返回商業(yè)數(shù)據(jù)的特殊頁(yè)面,否則響應(yīng)會(huì)由于不必要的標(biāo)記而非常龐大。

ASP.NET 2.0 中的帶外

  ASP.NET 2.0 概括了 XmlHttp 對(duì)象的使用并提供了內(nèi)置的回調(diào)功能。新系統(tǒng)的核心有兩個(gè)關(guān)鍵項(xiàng):System.Web.UI.ICallbackEventHandler 和 Page.GetCallbackEventReference 方法。

  Page.GetCallbackEventReference 方法及其重載用于指定將參與回調(diào)事件的 JavaScript 方法。

public string GetCallbackEventReference(
 Control control,
 string argument,
 string clientCallback,
 string context
);

  上述代碼顯示了 GetCallBackEventReference 所需的最小參數(shù)集,這些參數(shù)將在下面進(jìn)行詳細(xì)說(shuō)明。

  Control — control 參數(shù)確定實(shí)現(xiàn) RaiseCallbackEvent 方法的 ICallbackEventHandler。

  Argument — argument 字符串包含客戶(hù)端腳本。評(píng)估該腳本的結(jié)果將作為 eventArgument 參數(shù)傳遞到 RaiseCallbackEvent。

  ClientCallback — clientCallback 參數(shù)包含客戶(hù)端事件處理程序的名稱(chēng),該處理程序?qū)⒔邮粘晒Ψ?wù)器事件的結(jié)果。

  Context — context 參數(shù)包含一個(gè)客戶(hù)端腳本。評(píng)估該腳本的結(jié)果將傳遞到客戶(hù)端事件處理程序,該處理程序在 clientCallback 參數(shù)中指定為 context 參數(shù)。

 CallbackEventHandler 和 GetCallbackEventReference 方法相結(jié)合在客戶(hù)端和服務(wù)器之間產(chǎn)生異步通訊。


回調(diào)示例

  以下 Web 頁(yè)使用回調(diào)機(jī)制查詢(xún)服務(wù)器以獲得其當(dāng)前時(shí)間。該頁(yè)面彈出一個(gè) JavaScript 警告,在無(wú)需完整頁(yè)面回發(fā)的情況下顯示當(dāng)前時(shí)間。

<%@ Page Language=" C# " CompileWith="Default3.aspx.cs" ClassName="Default3_aspx" %>
<%@ Register TagPrefix="cc1" Namespace="MyControls" Assembly="WebControlLibrary3" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD X HTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script language="javascript">
 function GetServerTime() {
  var message = '';
  var context = '';
  <%=CallBack%>
 }
 function ShowServerTime(timeMessage, context) {
  alert('The time on the server is:\n' + timeMessage);
 }
 function OnError(message, context) {
  alert('An unhandled exception has occurred:\n' + message);
 }
</script>
</head>
<body>
<form id="form1" runat="server">
 <div>
  <cc1:timesnap id="TimeSnap1" runat="server"> </cc1:timesnap>
  <input type="button" value="GetTime" onclick="GetServerTime();" /> 
 </div>
</form>
</body>
</html>

  上述頁(yè)面源代碼包含三個(gè)關(guān)鍵 Java Script 函數(shù):GetServerTime()、ShowServerTime() 和 OnError()。這些 JavaScript 函數(shù)與頁(yè)面的 GetCallbackEventReference 帶外請(qǐng)求相關(guān)聯(lián)。

public partial class Default3_aspx {
 public string CallBack;
 void Page_Load(object sender, EventArgs e) {
  CallBack = this.GetCallbackEventReference(TimeSnap1,"message","ShowServerTime","context","OnError");
 }
}

  GetCallbackEventReference 方法需要為其第一個(gè)參數(shù)實(shí)現(xiàn) ICallbackEventHandler 接口的對(duì)象。通過(guò)實(shí)現(xiàn) RaiseCallbackEvent() 方法,TimeSnap 自定義服務(wù)器控件符合接口要求。

public class TimeSnap : WebControl, ICallbackEventHandler
{
 ...
 public string RaiseCallbackEvent(string eventArgument) {
  // Uncomment next line to test error handler
  // throw new ApplicationException(// "Some unhandled exception");
  return DateTime.Now.ToLocalTime().ToShortTimeString();
 }
}
}

  TimeSnap.RaiseCallbackEvent() 方法僅返回 string 格式的當(dāng)前時(shí)間。


圖 9. 回調(diào)請(qǐng)求輸出

  圖 9 說(shuō)明了按下 GetTime 按鈕的結(jié)果。向服務(wù)器發(fā)出帶外請(qǐng)求,從而產(chǎn)生顯示服務(wù)器上當(dāng)前時(shí)間的“Alert”窗口。發(fā)出這個(gè)請(qǐng)求不需要回發(fā),因此控件的最初生成時(shí)間不會(huì)改變。

使用 設(shè)計(jì)

  在前面的示例中,我們已經(jīng)使用了幾個(gè)標(biāo)準(zhǔn)的特性來(lái)規(guī)定自定義控件的屬性將與設(shè)計(jì)器 (Visual Studio) 進(jìn)行交互的方式。我們?yōu)楦鞣N控件屬性分配了特性以定義屬性將在其中出現(xiàn)的類(lèi)別、定義屬性是否應(yīng)該具有一個(gè)默認(rèn)值、定義屬性的說(shuō)明應(yīng)該是什么樣子以及屬性是否應(yīng)該為 bindable。在 ASP.NET 1.x 中,附加的設(shè)計(jì)器類(lèi) 使您可以創(chuàng)建用于編輯屬性的新對(duì)話(huà)框、自動(dòng)將屬性值從 String 轉(zhuǎn)換為其他數(shù)據(jù)類(lèi)型(反之亦然),并顯示只在運(yùn)行時(shí)生成的控件的占位符數(shù)據(jù)。

  設(shè)計(jì)器類(lèi)有助于將控件開(kāi)發(fā)分成兩個(gè)階段。第一,您必須開(kāi)發(fā)自定義控件。第二,您必須決定開(kāi)發(fā)人員將如何與設(shè)計(jì)環(huán)境內(nèi)的控件進(jìn)行交互。設(shè)計(jì)器類(lèi)通過(guò)在每個(gè)自定義控件的頂部充當(dāng)裝飾師來(lái)完成第二個(gè)任務(wù)。換句話(huà)說(shuō),如果您要開(kāi)發(fā)很多自定義控件,您可以創(chuàng)建一個(gè)標(biāo)準(zhǔn)的可重復(fù)使用的設(shè)計(jì)器集,并通過(guò)特性簡(jiǎn)單地將設(shè)計(jì)器應(yīng)用到每個(gè)自定義控件中。

ASP.NET 2.0 為 設(shè)計(jì) 器模型提供了幾項(xiàng)增強(qiáng)功能:

  1) 新的復(fù)合控件設(shè)計(jì)器 — CompositeControlDesiger 類(lèi)完全識(shí)別復(fù)合控件,并且提供支持父子控件關(guān)系的功能。

  2) 新的數(shù)據(jù)綁定控件設(shè)計(jì)器 — DataBoundControlDesigner 為 Databound 控件提供了很多新功能。您可以使用該設(shè)計(jì)器來(lái)提供模擬數(shù)據(jù),或者在設(shè)計(jì)期間自動(dòng)連接到活 datasource。

  3) 增強(qiáng)的備用設(shè)計(jì)時(shí)區(qū)域支持 — 新的 DesignerRegion 類(lèi)及其子類(lèi)提供了一種非常靈活的機(jī)制以便顯示控件。您可以使用 DesignerRegion 來(lái)設(shè)置控件的選項(xiàng)卡式視圖。您還可以使用 EditableDesignerRegion 控件為控件創(chuàng)建新的模板。

  4) 增強(qiáng)的模板支持 — 現(xiàn)在,設(shè)計(jì)器類(lèi)提供了更簡(jiǎn)潔的機(jī)制以便將新的模板添加到控件中。模板化控件是一種將控件邏輯和控件顯示分開(kāi)的控件。顯示通過(guò)模板進(jìn)行定義,而邏輯在實(shí)際控件中進(jìn)行編碼。

  5) 增強(qiáng)的任務(wù)支持 — 現(xiàn)在,設(shè)計(jì)器可以合并設(shè)計(jì)時(shí)的任務(wù)。最常見(jiàn)的任務(wù)將可在視圖之間切換。但是,其他任務(wù)可以包括控件的自動(dòng)配置或資源文件的自動(dòng)創(chuàng)建。任務(wù)可以在設(shè)計(jì)時(shí)控件上顯示為菜單(與允許您配置 GridView 控件的菜單相似)。

  6) 增強(qiáng)的事件支持 — 設(shè)計(jì)器中的事件模型已經(jīng)進(jìn)行了改進(jìn)。現(xiàn)在,您可以創(chuàng)建事件來(lái)響應(yīng)在不同區(qū)域中的單擊或?qū)Ω鞣N任務(wù)的單擊。使用設(shè)計(jì)器時(shí),只要用戶(hù)在特定區(qū)域上單擊就可以使控件切換視圖、自動(dòng)生成代碼或更改配置。

ASP .NET 2.0 具有一個(gè)經(jīng)過(guò)顯著改進(jìn)的設(shè)計(jì)器模型,它可以使專(zhuān)業(yè)控件開(kāi)發(fā)人員的工作更加簡(jiǎn)單。如果您只是為自己使用而構(gòu)建一個(gè)單個(gè)的控件,該設(shè)計(jì)器就大材小用了。但是,如果您要為分發(fā)而構(gòu)建一個(gè)控件,您可以使用新的設(shè)計(jì)器來(lái)全面地自定義 Visual Studio 2005 中控件的行為。

小結(jié)

  盡管 ASP.NET 2.0 包含了一個(gè)內(nèi)容豐富的擴(kuò)展控件集,但開(kāi)發(fā)人員通常有很多理由來(lái)創(chuàng)建自定義控件。由于 ASP.NET 2.0 中的增強(qiáng)功能,創(chuàng)建自定義控件的過(guò)程要比在 ASP.NET 1.x 中更快、更容易。新的 CompositeControl 基類(lèi)完全利用自適應(yīng)呈現(xiàn)模型,并為創(chuàng)建復(fù)雜的控件提供了一個(gè)簡(jiǎn)單、易于使用的容器。如果您的控件需要回發(fā)或回調(diào)功能,ASP.NET 2.0 簡(jiǎn)化了處理客戶(hù)端腳本文件和開(kāi)發(fā)帶外請(qǐng)求的過(guò)程。最后,在您開(kāi)發(fā)控件后,您可以使用各種設(shè)計(jì)器類(lèi)來(lái)完全配置控件在可視化設(shè)計(jì)器(例如 Visual Studio 2005)內(nèi)的行為。

詳細(xì)闡述利用ASP.NET 2.0創(chuàng)建自定義Web控件開(kāi)發(fā)說(shuō)明


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 乌拉特中旗| 宝鸡市| 石楼县| 裕民县| 台山市| 宁国市| 泰和县| 孝昌县| 吴江市| 万荣县| 深水埗区| 偏关县| 于都县| 依安县| 宁陕县| 怀远县| 攀枝花市| 瑞丽市| 龙泉市| 舟曲县| 莒南县| 郴州市| 景泰县| 汾阳市| 鄂州市| 延长县| 阿克苏市| 清水河县| 东港市| 西青区| 长岭县| 古交市| 社会| 开远市| 疏附县| 潮州市| 黄山市| 特克斯县| 毕节市| 枞阳县| 海丰县|