ASP.NET 2.0數(shù)據(jù)綁定機(jī)制:生成控件
ASP.NET 2.0數(shù)據(jù)綁定機(jī)制
要在 ASP.NET 2.0 中生成新的數(shù)據(jù)綁定控件,首先需要確定哪個(gè)類(lèi)能夠更好地適合您的要求。然而,您的選擇并不局限于比較空的類(lèi),如 Control 和 WebControl 甚至 ListControl。讓我們探索一下那些深藏于幕后的類(lèi)。BaseDataBoundControl 是所有數(shù)據(jù)綁定控件類(lèi)的根。它定義了 DataSource 和 DataSourceID 屬性,并且驗(yàn)證它們被分配的內(nèi)容。DataSource 接受按照 ASP.NET 1.x 的方式獲得和分配的可枚舉對(duì)象。
- Mycontrol1.DataSource = dataSet;
- Mycontrol1.DataBind();
DataSourceID 是一個(gè)字符串,并且是指綁定數(shù)據(jù)源組件的 ID。一旦將控件綁定到數(shù)據(jù)源,則二者之間的任何進(jìn)一步的交互(無(wú)論是讀還是寫(xiě))都將脫離您的控制范圍,并且不可見(jiàn)。這一點(diǎn)既有好的一面,也有壞的一面。好(更確切地說(shuō)是偉大)的一面在于可以消除大量代碼。ASP.NET 框架能夠保證正確的代碼得以執(zhí)行,并且按照公認(rèn)的最佳做法編寫(xiě)代碼。您的工作效率會(huì)更高,因?yàn)槟梢酝耆_信在工作過(guò)程中不會(huì)出現(xiàn)令人難以捉摸的錯(cuò)誤,從而可以更快地創(chuàng)作頁(yè)。如果您不喜歡這種情況(好像很多 ASP.NET 1.x 開(kāi)發(fā)人員都抱怨這種情況),則您可以繼續(xù)使用通過(guò) DataSource 屬性和 DataBind 方法完成的舊樣式的編程。而且,在這種情況下,基類(lèi)使您不必完成一些常見(jiàn)的工作,即使這種效果在代碼中體現(xiàn)得不是那么明顯。
DataBoundControl 類(lèi)用于與現(xiàn)有控件沒(méi)有多少共同點(diǎn)的標(biāo)準(zhǔn)的自定義數(shù)據(jù)綁定控件。如果您必須處理自己的數(shù)據(jù)項(xiàng)集合,管理視圖狀態(tài)和樣式,創(chuàng)建簡(jiǎn)單但量身定制的用戶(hù)界面,則該類(lèi)可以提供一個(gè)良好的起點(diǎn)。最為有趣的是,DataBoundControl 類(lèi)將控件連接到數(shù)據(jù)源組件,并且在 API 級(jí)別隱藏了可枚舉數(shù)據(jù)源和特別組件之間的任何差異。簡(jiǎn)而言之,當(dāng)您從該類(lèi)繼承時(shí),您只需要重寫(xiě)一個(gè)接收數(shù)據(jù)集合(無(wú)論數(shù)據(jù)源是 DataSet 對(duì)象還是較新的數(shù)據(jù)源組件)的方法。
讓我們?cè)敿?xì)闡述這一點(diǎn)(它代表體系結(jié)構(gòu)中的重大更改)。
BaseDataBoundControl 重寫(xiě)了 DataBind 方法(原來(lái)在 Control 上定義),并且使它調(diào)用 PerformSelect 方法(該方法被標(biāo)記為受保護(hù)的和抽象的)。正如其名稱(chēng)所暗示的那樣,PerformSelect 能夠檢索有效的數(shù)據(jù)集合以使綁定發(fā)生。該方法是受保護(hù)的,因?yàn)樗瑢?shí)現(xiàn)細(xì)節(jié);它是抽象的(用 Visual Basic 行話(huà)說(shuō)就是 MustInherit),因?yàn)樗男袨橹荒苡膳缮?lèi)(如 DataBoundControl)確定。
那么,DataBoundControl 完成哪些工作以重寫(xiě) PerformSelect 呢?
它連接到數(shù)據(jù)源對(duì)象并獲得默認(rèn)視圖。數(shù)據(jù)源對(duì)象(例如,像 SqlDataSource 或 ObjectDataSource 之類(lèi)的控件)執(zhí)行它的選擇命令并返回得到的集合。操作數(shù)據(jù)檢索的受保護(hù)方法(名為 GetData)還足夠聰明,以便檢查 DataSource 屬性。如果 DataSource 非空,則將綁定對(duì)象包裝到一個(gè)動(dòng)態(tài)創(chuàng)建的數(shù)據(jù)源視圖對(duì)象中,并且將其返回。
ASP.NET 2.0數(shù)據(jù)綁定機(jī)制:下一個(gè)步驟
下一個(gè)步驟需要您以控件開(kāi)發(fā)人員的身份參與。迄今為止,基類(lèi)已經(jīng)以一種完全自動(dòng)的方式從 ADO.NET 對(duì)象或數(shù)據(jù)源組件中檢索數(shù)據(jù)。下一個(gè)步驟取決于您期望該控件完成哪些任務(wù)。這里正好用到可重寫(xiě)的 PerformDataBinding 方法。以下代碼片段顯示了 DataBoundControl 中對(duì)該方法的實(shí)現(xiàn)。請(qǐng)注意,由框架傳遞給該方法的 IEnumerable 參數(shù)只包含要綁定的數(shù)據(jù)(不管它們的來(lái)源如何)。
- protected virtual void PerformDataBinding(IEnumerable data)
- {
- }
在自定義數(shù)據(jù)綁定控件中,您只需要重寫(xiě)該方法,并且填充任何特定于控件的集合,如包含很多個(gè)列表控件的 Items 集合(例如,CheckBoxList)??丶挠脩?hù)界面的呈現(xiàn)發(fā)生在 Render 方法或 CreateChildControls 中,具體取決于該控件的性質(zhì)。Render 適用于列表控件;而 CreateChildControls 則非常適合于復(fù)合控件。
有一件事情尚未解釋?zhuān)河烧l(shuí)啟動(dòng)數(shù)據(jù)綁定過(guò)程?在 ASP.NET 1.x 中,數(shù)據(jù)綁定需要顯式調(diào)用 DataBind 方法才能開(kāi)始工作。在 ASP.NET 2.0 中,如果您使用 DataSource 屬性將數(shù)據(jù)綁定到控件,則仍然需要這樣做。如果您改而通過(guò) DataSourceID 屬性使用數(shù)據(jù)源組件,則應(yīng)當(dāng)避免這樣做。數(shù)據(jù)綁定過(guò)程由 DataBoundControl 中定義的內(nèi)部 OnLoad 事件處理程序自動(dòng)觸發(fā),如下面的偽代碼所示。
- protected override void OnLoad(EventArgs e)
- {
- this.ConnectToDataSourceView();
- if (!Page.IsPostBack)
- base.RequiresDataBinding = true;
- base.OnLoad(e);
- }
每當(dāng)該控件被加載到頁(yè)中的時(shí)候(回發(fā)或首次加載),都會(huì)檢索和綁定數(shù)據(jù)。需要由數(shù)據(jù)源決定是再次運(yùn)行查詢(xún)還是使用一些緩存數(shù)據(jù)。
如果該頁(yè)是首次顯示,則還會(huì)啟用 RequiresDataBinding 屬性以要求綁定數(shù)據(jù)。當(dāng)分配的值為 true 時(shí),該屬性的設(shè)置程序會(huì)在內(nèi)部調(diào)用 DataBind。下面的偽代碼顯示了 RequiresDataBinding 設(shè)置程序的內(nèi)部實(shí)現(xiàn)。
- protected void set_RequiresDataBinding(bool value)
- {
- if (value && (DataSourceID.Length > 0))
- DataBind();
- else
- _requiresDataBinding = value;
- }
正如您可以看到的那樣,為了向后兼容,僅當(dāng) DataSourceID 不為空(即您綁定到 ASP.NET 2.0 數(shù)據(jù)源控件)時(shí),才會(huì)發(fā)生對(duì) DataBind 的自動(dòng)調(diào)用。有鑒于此,如果您還顯式調(diào)用 DataBind,則會(huì)導(dǎo)致雙重?cái)?shù)據(jù)綁定。
請(qǐng)注意,您無(wú)法同時(shí)設(shè)置 DataSource 和 DataSourceID。當(dāng)發(fā)生這種情況時(shí),將引發(fā)無(wú)效操作異常。
最后,稍微提一下 EnsureDataBound 這一受保護(hù)的方法。該方法是在 BaseDataBoundControl 類(lèi)上定義的,它能夠確??丶呀?jīng)被正確地綁定到必需的數(shù)據(jù)。如果 RequiresDataBinding 為 true,則該方法調(diào)用 DataBind,如下面的代碼片段所示。
- protected void EnsureDataBound()
- {
- if (RequiresDataBinding && (DataSourceID.Length > 0))
- DataBind();
- }
如果您已經(jīng)編寫(xiě)了復(fù)雜且完善的數(shù)據(jù)綁定控件,則您很可能已經(jīng)知道我的意思。在 ASP.NET 1.x 中,在下列兩種情況下,通常會(huì)將數(shù)據(jù)綁定控件設(shè)計(jì)為生成它自己的用戶(hù)界面:該控件具有對(duì)數(shù)據(jù)源的完全訪(fǎng)問(wèn)權(quán)限,或者該控件基于視圖狀態(tài)。當(dāng)該控件需要管理它自己的回發(fā)事件時(shí)(例如,假設(shè)該控件是支持分頁(yè)的 DataGrid),則前面提到的兩個(gè)選擇似乎是兩種極端的情況。在 ASP.NET 1.x 中,這些控件(同樣,請(qǐng)考慮 DataGrid)只有一種解決辦法:向要刷新的主頁(yè)引發(fā)事件。該方法導(dǎo)致 ASP.NET 1.x 頁(yè)中存在多余代碼這一眾所周知的問(wèn)題 — 這也正是調(diào)用數(shù)據(jù)源組件來(lái)加以修復(fù)的問(wèn)題。
在 ASP.NET 2.0 中,每當(dāng)在控件的生存期中發(fā)生要求綁定數(shù)據(jù)的事情時(shí),都需要將 RequiresDataBinding 設(shè)置為 true。設(shè)置該屬性會(huì)觸發(fā)相應(yīng)的數(shù)據(jù)綁定機(jī)制,從而重新創(chuàng)建該控件的內(nèi)部基礎(chǔ)結(jié)構(gòu)的更新版本。內(nèi)置的 OnLoad 事件處理程序還會(huì)將該控件連接到數(shù)據(jù)源。為了確實(shí)有效,該技術(shù)必須依賴(lài)于能夠?qū)⑺鼈兊臄?shù)據(jù)緩存在某個(gè)位置的智能數(shù)據(jù)源控件。例如,SqlDataSource 控件支持很多屬性,以便在給定期限內(nèi)將任何綁定結(jié)果集存儲(chǔ)到 ASP.NET 緩存中。
以上就介紹了ASP.NET 2.0數(shù)據(jù)綁定機(jī)制:如何生成新的數(shù)據(jù)綁定控件。
【編輯推薦】