国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

ASP.NET組件設計Step by Step(8)

2024-07-10 12:56:51
字體:
來源:轉載
供稿:網友
控制控件的樣式



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

如果對樣式無特殊要求,直接繼承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是只讀屬性,在第一次訪問時被創(chuàng)建(這個思想繼承了.net的jit方案)。

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

protected virtual style createcontrolstyle()

{

return new style(viewsatte);

}

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

作為控件開發(fā)者,可以自定義繼承自style的屬性,例如,mytable控件定義一個tablecontrol類型,添加table支持的cellpadding/cellspaceing等屬性。

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

1、 覆蓋受保護的虛函數(shù)createcontrolstyle

2、 利用applystyle(style s)方法將自定義的屬性復制到控件自己的controlstyle中去

3、 mergestyle(style s)合并方法到controlstyle中去



我們看到,控件的controlstyle屬性和其他子屬性都是公用一個statebag的。因為控件style生成時候是調用傳遞viewstate的構造函數(shù)。另外,子控件也是采用同一個stateebag來存儲狀態(tài)的。





復合控件

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

復合控件包含多個已存控件,復用子控件提供的功能。譬如,當要編寫的復合控件包含textbox時候,就不必自己實現(xiàn)ipostbackdatahandler接口。復合控件可以派生子control類或者webcontrol類,復合的要點是:

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

2、 實現(xiàn)system..web.ui.inamingcontainer接口,從而在復合控件下建立一個新的命名范圍。inamingcontainer僅僅是一個標記接口,讓框架自動實現(xiàn)子控件的唯一命名。

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



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



復合控件視圖狀態(tài)如何工作?

control內建了跟蹤、保存和恢復子控件的狀態(tài)。

在開始跟蹤視圖狀態(tài)階段中,control依次調用controls集合中的控件的trackvierstate方法,跟蹤子控件的狀態(tài)。如果子控件是在父控件中打開狀態(tài)下加入到controls中,那么在添加到集合時候調用trackviewstate方法。

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

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



事件冒泡

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

例如:數(shù)據(jù)綁定控件(repeater、datalist 和 datagrid)使用事件冒泡將子控件(在項目模板內)引發(fā)的命令事件公開為頂級事件。雖然 .net 框架中的 asp.net 服務器控件將事件冒泡用于命令事件(事件數(shù)據(jù)類是從 commandeventargs 派生的事件),但是,服務器控件上定義的任何事件都可以冒泡。

控件可以通過從基類 system.web.ui.control 繼承的兩個方法參與事件冒泡。這兩個方法是:onbubbleevent 和 raisebubbleevent。以下代碼片段顯示了這些方法的簽名。

protected virtual bool onbubbleevent(

object source,

eventargs args

);

protected void raisebubbleevent(

object source,

eventargs args

);

raisebubbleevent 的實現(xiàn)是由 control 提供的,并且不能被重寫。raisebubbleevent 沿層次結構向上將事件數(shù)據(jù)發(fā)送到控件的父級。若要處理或引發(fā)冒泡的事件,控件必須重寫 onbubbleevent 方法。



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

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

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

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、控件停止事件冒泡并引發(fā)和/或處理該事件。引發(fā)事件需要調用將事件調度給偵聽器的方法。若要引發(fā)冒泡的事件,控件必須重寫 onbubbleevent 以調用引發(fā)此冒泡的事件的 oneventname 方法。引發(fā)冒泡的事件的控件通常將冒泡的事件公開為頂級事件。

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;

}



模板化控件

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

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

1、實現(xiàn) system.web.ui.inamingcontainer 接口。這是沒有任何方法的標記接口。它可以在您的控件下創(chuàng)建新的命名范圍,這樣子控件就在名稱樹中有了唯一的標識符。

public class templatedfirstcontrol : control,inamingcontainer {...}

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

[ parsechildren(childrenasproperties = true)]

public class templatedfirstcontrol : control, inamingcontainer {...}

3、定義 system.web.ui.itemplate 類型的一個或多個屬性。itemplate 有一個方法 instantiatein,該方法可使用頁上內聯(lián)提供的模板創(chuàng)建控件。不必實現(xiàn) instantiatein 方法;asp.net 頁框架可提供這種實現(xiàn)。itemplate 屬性必須有 system.web.ui.templatecontainerattribute 類型的元數(shù)據(jù)屬性,它指出哪種 inamingcontainer 控件將擁有實例化模板。這在步驟 4 中作了說明。如下代碼所示定義了一個模板屬性。

[templatecontainer(typeof(firsttemplatecontainer))]

public itemplate firsttemplate {...}

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

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

public class firsttemplatecontainer : control, inamingcontainer {...}

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

實例化模板容器。

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

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

以下代碼片段說明了 createchildcontrols 的實現(xiàn)。

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 方法。這樣可保證在頁框架嘗試計算模板內任何數(shù)據(jù)綁定表達式之前,創(chuàng)建模板中的子控件。您還必須調用基類的 ondatabinding 方法以確保調用已注冊的事件處理程序。

protected override void ondatabinding(eventargs e) {

ensurechildcontrols();

base.ondatabinding(e);

}

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

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

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

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 株洲市| 镇雄县| 师宗县| 峡江县| 宁津县| 利川市| 全南县| 桓台县| 砀山县| 定州市| 阜新| 富源县| 姚安县| 汪清县| 满洲里市| 吉水县| 雅江县| 定陶县| 乌兰察布市| 长宁区| 巴中市| 淅川县| 西乡县| 临猗县| 西青区| 林西县| 赣州市| 遂平县| 泰和县| 陵水| 福贡县| 松原市| 阿合奇县| 叶城县| 宝丰县| 湘阴县| 老河口市| 抚顺县| 陵川县| 军事| 新密市|