日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET组件设计Step by Step(8)

發布時間:2025/3/15 asp.net 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET组件设计Step by Step(8) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

控制控件的樣式

?

控件最終通常要生成HTML代碼在客戶端,這些HTML元素可以采用豐富的CSS樣式。你當然可以直接進行CSS 設定,但是asp.net給控件開發者提供了編程方式控制樣式的途徑。

如果對樣式無特殊要求,直接繼承webControl的樣式功能即可,如果需要修改或者擴充繼承的樣式功能,則需要深入了解控件樣式的背景知識

WebControl的樣式功能全部封裝在ControlStyle屬性中(一個名為Style System.Web.UI.WebControls.Style的屬性)。所有樣式屬性都是ControlStyle屬性的子屬性。WebControl的ControlStyle的定義為:

Private Style _contentStyle;

……

public Style ControlStyle

{

?????? get

????????????? {

????????????? ?????? if(_contentStyle = = null)

???????????????????? ?????? {

???????????????????? ?????? ?????? _contentStyle=CreateControlStyle();

???????????????????? ?????? ?????? if(IsTrackingViewState)

???????????????????? ???????????????????? {

???????????????????? ???????????????????? ?????? ((IStateManager)_controlStyle).TrackViewState();

}

???????????????????? ?????? }

????????????? ?????? return?_contentStyle;

????????????? }

}

我們看到,ControlStyle是只讀屬性,在第一次訪問時被創建(這個思想繼承了.net的JIT方案)。

那么這個CreateControlStyle到底是什么回事?

Protected virtual Style CreateControlStyle()

{

?????? return new Style(ViewSatte);

}

原來也是讀取ViewState得到的。這樣,無論是你從.aspx頁面中關于控件聲明中定義的還是通過編程設定的都可以在存取時反映得到。

作為控件開發者,可以自定義繼承自Style的屬性,例如,MyTable控件定義一個TableControl類型,添加Table支持的cellpadding\CellSpaceing等屬性。

編程控制屬性有3種途徑:

1、?覆蓋受保護的虛函數CreateControlStyle

2、?利用ApplyStyle(Style s)方法將自定義的屬性復制到控件自己的ControlStyle中去

3、?MergeStyle(Style s)合并方法到ControlStyle中去

?

我們看到,控件的ControlStyle屬性和其他子屬性都是公用一個StateBag的。因為控件style生成時候是調用傳遞ViewState的構造函數。另外,子控件也是采用同一個StateeBag來存儲狀態的。

?

?

復合控件

首先明確復合控件不同于用戶控件,因為它是編譯后的形式出現的,而用戶控件則以文本形式部署。但共同點都是類復用來復用他們的功能。

復合控件包含多個已存控件,復用子控件提供的功能。譬如,當要編寫的復合控件包含TextBox時候,就不必自己實現IPostBackDataHandler接口。復合控件可以派生子Control類或者WebControl類,復合的要點是:

1、?重載CreateChildControl方法來對子控件進行實例化、初始化,并將子控件添加到控件樹中(加入到page的控件樹從而獲得控件的生命周期)。需要避免的是不可在OnInit事件中執行業務邏輯。

2、?實現System..Web.UI.InamingContainer接口,從而在復合控件下建立一個新的命名范圍。InamingContainer僅僅是一個標記接口,讓框架自動實現子控件的唯一命名。

為什么必須在CreateChildControls方法中創建子控件呢?實際上,這樣做是為了可以在控件生命周期中任何需要的時候來創建子控件,而且可以利用子控件來處理諸如會傳數據等任務。為了確保子控件在代碼訪問其之前創建好,Controllei定義的EnsureChildControls保護方法來檢查子控件是夠已經創建好,如果沒有創建,,就可以調用CreateChildControls方法來創建。如果子控件沒有在render之前被創建,那么缺省情況下visible為true的未被創建的子控件會被PreRender方法的默認實現調用EnsureChildControls。

?

復合可以重用,但是也會帶來性能損失(例如子控件實例化等)。所以,需要在性能和易用之間權衡,要么復合控件,要么干脆自己編寫完全生成控件。

?

復合控件視圖狀態如何工作?

Control內建了跟蹤、保存和恢復子控件的狀態。

在開始跟蹤視圖狀態階段中,Control依次調用Controls集合中的控件的TrackVierState方法,跟蹤子控件的狀態。如果子控件是在父控件中打開狀態下加入到Controls中,那么在添加到集合時候調用TrackViewState方法。

在保存視圖狀態階段,Control首先調用SaveViewSate方法,默認情況下首先調用ViewState字典的SaveViewState。并保存所返回的對象,作為控件視圖的第一部分;接下來,Control調用每一個子控件的SaveViewState,如果返回的子控件不為空,那么由Control在兩個ArrayList中保存子控件的編號和對應狀態,用來進行串行化。

在加載視圖狀態階段,control先調用LoadViewState方法恢復上一次保存的狀態第一部分,接下來Control訪問Controls集合,將剩下的狀態加載入子控件,一般通過編號和保存狀態的ArrayList來組成,這樣就恢復了控件及其子控件的轉臺。如果在此階段還沒有創建子控件,那么先保存子控件狀態,留做以后使用,直到子控件創建后加載給子控件。

?

事件冒泡

ASP.NET 頁框架提供一種稱為“事件冒泡”的技術,允許子控件將事件沿其包容層次結構向上傳播。事件冒泡允許在控件層次結構中更方便的位置引發事件,并且允許將事件處理程序附加到原始控件以及公開冒泡的事件的控件上。

例如:數據綁定控件(Repeater、DataList 和 DataGrid)使用事件冒泡將子控件(在項目模板內)引發的命令事件公開為頂級事件。雖然 .NET 框架中的 ASP.NET 服務器控件將事件冒泡用于命令事件(事件數據類是從 CommandEventArgs 派生的事件),但是,服務器控件上定義的任何事件都可以冒泡。

控件可以通過從基類 System.Web.UI.Control 繼承的兩個方法參與事件冒泡。這兩個方法是:OnBubbleEvent 和 RaiseBubbleEvent。以下代碼片段顯示了這些方法的簽名。

protected virtual bool OnBubbleEvent(

?? object source,

?? EventArgs args

);

protected void RaiseBubbleEvent(

?? object source,

?? EventArgs args

);

RaiseBubbleEvent 的實現是由 Control 提供的,并且不能被重寫。RaiseBubbleEvent 沿層次結構向上將事件數據發送到控件的父級。若要處理或引發冒泡的事件,控件必須重寫 OnBubbleEvent 方法。

?

使事件冒泡的控件執行以下三種操作之一。

1、控件不執行任何操作,此時事件自動向上冒泡到其父級。

2、控件進行一些處理并繼續使事件冒泡。若要實現這一點,控件必須重寫 OnBubbleEvent,并從 OnBubbleEvent 調用 RaiseBubbleEvent。以下代碼片段(摘自模板化數據綁定控件示例)在檢查事件參數的類型后使事件冒泡。

protected override bool OnBubbleEvent(object source, EventArgs e) {

??????????? if (e ?is CommandEventArgs) {???????????????

??????????????? TemplatedListCommandEventArgs args =

??????????????????? new TemplatedListCommandEventArgs(this, source, (CommandEventArgs)e);

??????????????? RaiseBubbleEvent(this, args);

??????????????? return true;

??????????? }

??????????? return false;

??????? }

3、控件停止事件冒泡并引發和/或處理該事件。引發事件需要調用將事件調度給偵聽器的方法。若要引發冒泡的事件,控件必須重寫 OnBubbleEvent 以調用引發此冒泡的事件的 OnEventName 方法。引發冒泡的事件的控件通常將冒泡的事件公開為頂級事件。

protected override bool OnBubbleEvent(object source, EventArgs e) {

??? bool handled = false;

??? if (e is TemplatedListCommandEventArgs) {

??? ????TemplatedListCommandEventArgs ce = (TemplatedListCommandEventArgs)e;

??????? OnItemCommand(ce);

??????? handled = true;

??? }

??? return handled;

}

?

模板化控件

使用模版化控件,控件開發者可以通過template指定生成的全部或者部分UI。模板是頁面語法的一部分,可以包括靜態的HTML(HTML語法表達的控件實際上是子控件,但是屬于LiteralControl控件)以及其他文自文本的服務器控件。模板功能,允許將控制數據與其表示分開。模板控件本身不提供用戶界面 (UI)。該控件的 UI 由頁面開發人員通過內聯模板提供,該模板允許頁面開發人員自定義該控件的 UI。通過使用模板,控件生成不同于樣式的UI,但是這種UI能力主要是產生頁面元素。譬如repeater控件等。

要支持模板化,控件必須實現Itemplate接口。頁面解析器解析模板標簽內的文本,并生成一個解析樹來表示模板的內容,就像解析整個Page一樣。支持模板控件開發需要做到:

1、實現 System.Web.UI.INamingContainer 接口。這是沒有任何方法的標記接口。它可以在您的控件下創建新的命名范圍,這樣子控件就在名稱樹中有了唯一的標識符。

public class TemplatedFirstControl : Control,INamingContainer {...}

2、將 ParseChildrenAttribute 應用到控件,并傳遞 true 作為參數。在 ASP.NET 頁上聲明性地使用控件時,這樣可指示頁分析器如何分析模板屬性標記。步驟 3 說明如何定義一個模板屬性。 注意 如果您的控件是從 WebControl 派生的,則不需要應用 ParseChildrenAttribute,因為 WebControl 已經用該屬性作了標記。

[ ParseChildren(ChildrenAsProperties = true)]

public class TemplatedFirstControl : Control, INamingContainer {...}

3、定義 System.Web.UI.ITemplate 類型的一個或多個屬性。ITemplate 有一個方法 InstantiateIn,該方法可使用頁上內聯提供的模板創建控件。不必實現 InstantiateIn 方法;ASP.NET 頁框架可提供這種實現。ITemplate 屬性必須有 System.Web.UI.TemplateContainerAttribute 類型的元數據屬性,它指出哪種 INamingContainer 控件將擁有實例化模板。這在步驟 4 中作了說明。如下代碼所示定義了一個模板屬性。

[TemplateContainer(typeof(FirstTemplateContainer))] ????????????????

?public ITemplate FirstTemplate {...}

4、TemplateContainerAttribute 的參數是您想在其中實例化模板的容器控件類型。容器控件獨立于正在創作的模板控件。具有邏輯容器的原因是:模板控件通常有一個模板,該模板需要使用不同數據重復實例化。擁有與根模板控件不同的容器控件,使擁有多個此類示例成為可能。邏輯容器是該模板內子控件的即時 INamingContainer。在開發模板化數據綁定控件中更詳細地介紹了這種關系。

注意 容器控件本身必須實現 INamingContainer,因為它有需要在頁上唯一命名的子控件。但是容器僅僅是容器,對應需要解釋的模板內容,并非控件。

public class FirstTemplateContainer : Control, INamingContainer {...}

5、重寫 CreateChildControls 方法以便在模板中創建子控件。這是通過三個步驟來完成的。

實例化模板容器。

調用模板屬性的 InstantiateIn 方法并將該容器作為參數傳遞給它。InstantiateIn 方法(在 ITemplate 接口中聲明)實例化該模板的元素,作為該模板容器的子控件。不必實現 InstantiateIn 方法;ASP.NET 頁框架可提供這種實現。

將模板容器的示例添加到您的模板控件的 Controls 集合。

以下代碼片段說明了 CreateChildControls 的實現。

private Control myTemplateContainer;

protected override void CreateChildControls ()

{

?? if (FirstTemplate != null)

?? {

????? myTemplateContainer = new FirstTemplateContainer(this);

????? FirstTemplate.InstantiateIn(myTemplateContainer);

????? Controls.Add(myTemplateContainer);

??? ?????? }

??? else

??? {

??????? Controls.Add(new LiteralControl(Text + " " + DateTime));

??? }

?}

5、重寫從 Control 繼承的 OnDataBinding 方法以調用 EnsureChildControls 方法。這樣可保證在頁框架嘗試計算模板內任何數據綁定表達式之前,創建模板中的子控件。您還必須調用基類的 OnDataBinding 方法以確保調用已注冊的事件處理程序。

??????? protected override void OnDataBinding(EventArgs e) {

??????????? EnsureChildControls();

??????????? base.OnDataBinding(e);

??????? }

7、在步驟 5 中,在 CreateChildControls 方法內重復該邏輯,以便為控件的每個模板屬性實例化一個模板。

我們看到,通常情況下我們在模板內指定的Container實際上需要我們控件開發者自行定義。實際上如果不重復生成子控件,InamingContainer也可不實現。但是開始提醒需要實現此接口。如果要在控件中支持數據綁定,那么模板容器應該由一個或者多個屬性代表綁定的數據。通常模板類作為控件類的內部私有類實現。

控件可以重復實例化某個模板(只要在不同的容器實例中即可),因此,模板不應該包含或者假定任何控件實例作為成員變量,因為在每次模板實例化時候,成員變量都可以用新的值來重寫。

?

轉載于:https://www.cnblogs.com/jasononline/archive/2007/06/07/775459.html

總結

以上是生活随笔為你收集整理的ASP.NET组件设计Step by Step(8)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。