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