溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ASP.NET復(fù)合控件原理及要點(diǎn)分別是什么

發(fā)布時(shí)間:2021-11-22 18:29:22 來源:億速云 閱讀:163 作者:柒染 欄目:編程語(yǔ)言

ASP.NET復(fù)合控件原理及要點(diǎn)分別是什么,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

ASP.NET復(fù)合控件簡(jiǎn)介

復(fù)合控件只不過是普通的 ASP.NET 控件,還不屬于要論及的另一種類型的 ASP.NET 服務(wù)器控件。既然這樣,為什么在各書籍和文檔中總要留出專門的章節(jié)來論述復(fù)合控件呢?ASP.NET復(fù)合控件有什么特別之處呢?

顧名思義,復(fù)合控件是將多個(gè)其他控件聚集在某單一頂部和單一 API 下的控件。如果某個(gè)自定義控件由一個(gè)標(biāo)簽和一個(gè)文本框組成,就可以說該控件是一個(gè)復(fù)合控件?!皬?fù)合”一詞表明該控件本質(zhì)上是由其他構(gòu)成組件在運(yùn)行時(shí)組合而成。復(fù)合控件所暴露的方法集和屬性集通常(但不是必須)由構(gòu)成組件的方法和屬性提供,并加入一些新成員。復(fù)合控件也可以引發(fā)自定義事件,還可以處理并激起子控件所引起的事件。

復(fù)合控件在 ASP.NET 中如此特別并不是因?yàn)槠溆锌赡艹蔀榉?wù)器控件新類型的代表。更確切的說是因?yàn)樗诔尸F(xiàn)時(shí)獲得了 ASP.NET 運(yùn)行時(shí)的支持。

復(fù)合控件是一個(gè)功能強(qiáng)大的工具,可以生成豐富復(fù)雜的組件,這些組件產(chǎn)生自活動(dòng)對(duì)象的相互作用而不是某些字符串生成器對(duì)象的標(biāo)記輸出。復(fù)合控件以構(gòu)成控件樹的形式呈現(xiàn),每個(gè)構(gòu)成控件都有其自己的生命周期和事件,并且所有構(gòu)成控件都聯(lián)合構(gòu)成一個(gè)全新的 API,并按需要盡可能地抽象化。

在本文中,我將論述復(fù)合控件的內(nèi)部體系結(jié)構(gòu),以闡明它在多種情況下為您帶來的好處。接下來,我將生成一個(gè)復(fù)合列表控件,與我在以前文章中所述控件的功能集相比,此控件的功能集更為豐富。

ASP.NET復(fù)合控件的要點(diǎn)是什么?

前一段時(shí)間,我曾經(jīng)自己嘗試在 ASP.NET. 中研究復(fù)合控件。我從 MSDN 文檔學(xué)習(xí)理論和實(shí)踐知識(shí),并也設(shè)計(jì)出一些不錯(cuò)的控件。但是,只有當(dāng)我有一次在純屬偶然的情況下看到以下示例時(shí),我才真正領(lǐng)悟到復(fù)合控件的要點(diǎn)(和優(yōu)點(diǎn))。設(shè)想一下由兩個(gè)其他控件(Label 和 TextBox)的組合生成的迄今為止最簡(jiǎn)單(也是最常見)的控件。以下介紹了一種編寫這種控件的可行方法。我們將其命名為 LabelTextBox。

public class LabelTextBox :WebControl, INamingContainer  {  public string Text {  get {  object o = ViewState["Text"];  if (o == null)  return String.Empty;  return (string) o;        }  set { ViewState["Text"] = value; }     }  public string Title {  get {  object o = ViewState["Title"];  if (o == null)  return String.Empty;  return (string) o;        }  set { ViewState["Title"] = value; }     }  protected override void CreateChildControls()     {  Controls.Clear();  CreateControlHierarchy();  ClearChildViewState();     }  protected virtual void CreateControlHierarchy()     {  TextBox t = new TextBox();  Label l = new Label();  t.Text = Text;  l.Text = Title;  Controls.Add(l);  Controls.Add(t);     }  }

該控件具備兩個(gè)公共屬性(Text 和 Title)以及一個(gè)呈現(xiàn)引擎。這兩個(gè)屬性保存在視圖狀態(tài)中,并分別表示 TextBox 和 Label 的內(nèi)容。該控件對(duì)于 Render 方法沒有替換方法,并通過 CreateChildControls 替換方法來生成其自己的標(biāo)記。我馬上就會(huì)詳述呈現(xiàn)階段的例行過程。CreateChildControls 的代碼首先清除子控件的集合,然后為當(dāng)前控件輸出的構(gòu)成控件生成控件樹。CreateControlHierarchy 是一種特定于控件的方法,不要求必須標(biāo)記為受保護(hù)和虛擬。但請(qǐng)注意,大多數(shù)自帶復(fù)合控件(例如 DataGrid)只是通過一個(gè)類似的虛擬方法來暴露用于生成控件樹的邏輯。

CreateControlHierarchy 方法會(huì)根據(jù)需要實(shí)例化多個(gè)構(gòu)成組件,然后合成最終輸出。完成之后,各控件將被添加到當(dāng)前控件的 Controls 集合。如果希望控件的輸出結(jié)果是一個(gè) HTML 表,則可以創(chuàng)建一個(gè) Table 控件,并相應(yīng)添加含有各自內(nèi)容的行和單元格。所有行、單元格和所含控件都是最外部表的子項(xiàng)。這時(shí),您只需將 Table 控件添加到 Controls 集合中即可。在上述代碼中,Label 和 TextBox 是 LabelTextBox 控件的直接子項(xiàng)并直接添加到集合中??丶某尸F(xiàn)狀態(tài)和運(yùn)行狀態(tài)都很正常。

單純從性能上看,創(chuàng)建控件的暫態(tài)實(shí)例不如呈現(xiàn)一些純文本的效率高。讓我們考慮一種無需子控件就能編寫上述控件的替代方法。這次讓我們將其命名為 TextBoxLabel。

public class LabelTextBox :WebControl, INamingContainer  {     :  protected override void Render(HtmlTextWriter writer)     {  string markup = String.Format(  "< span>{0}< /span>< input type=text value='{1}'>",  Title, Text);  writer.Write(markup);     }  }

該控件具備同樣的兩個(gè)屬性(Text 和 Title)并替換了 Render 方法。正如您所看到的那樣,其實(shí)現(xiàn)過程相當(dāng)簡(jiǎn)單并且代碼運(yùn)行速度也略勝一籌。您可以通過在字符串生成器中合成文本并為瀏覽器輸出最終標(biāo)記來取代合成子控件的這種方法。同樣,此時(shí)控件的呈現(xiàn)狀態(tài)良好。但我們真的可以說它的運(yùn)行狀態(tài)也同樣良好嗎?圖 1 顯示了在示例頁(yè)中運(yùn)行的兩個(gè)控件。

ASP.NET復(fù)合控件原理及要點(diǎn)分別是什么

圖 1:使用不同呈現(xiàn)引擎的相似控件

在頁(yè)面中啟用跟蹤功能并重新運(yùn)行。當(dāng)頁(yè)面顯示在瀏覽器中時(shí),將其向下滾動(dòng)并查看控件樹。它將如下所示:

ASP.NET復(fù)合控件原理及要點(diǎn)分別是什么

圖 2:由兩個(gè)控件生成的控件樹

ASP.NET復(fù)合控件由構(gòu)成組件的活動(dòng)實(shí)例組成。ASP.NET 運(yùn)行時(shí)會(huì)發(fā)現(xiàn)這些子控件,并可以在處理已發(fā)布數(shù)據(jù)時(shí)同它們進(jìn)行直接通信。其結(jié)果是,子控件可以自己處理視圖狀態(tài)并自動(dòng)激起事件。

對(duì)于基于標(biāo)記合成的控件,情況則不同。如圖中所示,該控件是一個(gè)帶有空 Controls 集合的代碼基本單位。如果標(biāo)記在頁(yè)面中注入交互元素(文本框、按鈕、下拉式菜單),則 ASP.NET 在不涉及控件本身的情況下無法處理回發(fā)數(shù)據(jù)及事件。

嘗試在兩個(gè)文本框中輸入一些文本并單擊圖 1 中的“刷新”按鈕,這樣就可以發(fā)生一個(gè)回發(fā)。***個(gè)控件(即復(fù)合控件)在經(jīng)過回發(fā)后會(huì)正確保留所分配的文本。使用 Render 方法的第二個(gè)控件在經(jīng)過回發(fā)后會(huì)丟失新文本。為什么會(huì)這樣呢?其中兼有兩個(gè)原因。

***個(gè)原因是,在上述標(biāo)記中我沒有為 < input> 標(biāo)記命名。這樣,它的內(nèi)容就不會(huì)回發(fā)。請(qǐng)注意,必須使用 name 屬性來為元素命名。讓我們對(duì) Render 方法做如下修改。

protected override void Render(HtmlTextWriter writer)  {  string markup = String.Format(  "< span>{0}< /span>< input type=text value='{1}' name='{2}'>",  Title, Text, ClientID);  writer.Write(markup);  }

注入客戶端頁(yè)面的 < input> 元素現(xiàn)在與服務(wù)器控件使用相同的 ID。頁(yè)面回發(fā)時(shí),ASP.NET 運(yùn)行時(shí)可發(fā)現(xiàn)一個(gè)與已發(fā)布字段的 ID 相匹配的服務(wù)器控件。但它并不知道如何處理該控件。要使 ASP.NET 將所有的客戶端更改都應(yīng)用于服務(wù)器控件,該控件必須實(shí)現(xiàn) IPostBackDataHandler 接口。

包含 TextBox 的復(fù)合控件無需擔(dān)心回發(fā)問題,因?yàn)樗度氲目丶?huì)使用 ASP.NET 自動(dòng)解決該問題。呈現(xiàn) TextBox 的控件需要與 ASP.NET 進(jìn)行交互,以確??梢哉_處理回發(fā)值并正常引發(fā)事件。以下代碼表明了如何擴(kuò)展 TextBoxLabel 控件以使其完全支持回發(fā)。

bool LoadPostData(string postDataKey, NameValueCollection postCollection)  {  string currentText = Text;  string postedText = postCollection[postDataKey];  if (!currentText.Equals(postedText, StringComparison.Ordinal))      {  Text = postedText;  return true;      }  return false;  }  void IPostBackDataHandler.RaisePostDataChangedEvent()  {  return;  }

關(guān)于ASP.NET復(fù)合控件原理及要點(diǎn)分別是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI