用於顯示分層資料的嵌套網格(from msdn)

來源:互聯網
上載者:User
資料|顯示 在“前沿技術”的 2003 年 8 月刊,我討論了如何擴充 ASP.NET DataGrid 伺服器控制項,以便將多表資料容器(如 DataSet 對象)用作其資料來源。 如果 DataSet 包含數對相關表,則只要所顯示的表是其中某個關係的父級,該控制項就將添加動態建立的按鈕列。 當單擊此列按鈕時,將顯示子 DataGrid,並將根據此關係列出選定記錄的子行。 總體行為顯示在圖 1 中,此行為與 Windows® 表單 DataGrid 控制項在類似情形下的工作方式相同。



圖 1 父級和子級 DataGrids

圖 1 中顯示的應用程式是包含兩個一起工作的 DataGrid 控制項的使用者控制項。 該使用者控制項(請參閱 2003 年 8 月的原始碼)包含使兩個網格保持同步所需的全部邏輯。 父 DataGrid 綁定到 DataSet 並顯示父表的內容。 當這一情況發生時,該使用者控制項確保 DataSet(所顯示的表在其中充當父級)內部存在關係。 子 DataGrid 綁定到資料檢視,該視圖包含僅僅與選定記錄相關的子表中的所有記錄。 因此,如果您有一個 DataSet,並且它有兩個已建立關係的表,那麼該使用者控制項將為您節省時間,因為您不需要針對任何額外的顯示機制來編寫代碼。

那麼這種方法有什麼問題呢? 如果您僅僅關注準系統,那麼它沒有問題。 但是,一些讀者已注意到不使用兩個物理上分隔的 DataGrid 控制項也許會更好。 該使用者控制項在組成控制項的周圍構建了一個壁壘,從而使您只能通過映射屬性和方法或者通過公開整個內部控制項來訪問這些組成控制項。 從可程式化性的觀點來看,使用一個 DataGrid 控制項來顯示分層資料要簡單得多。 首先,您不必擔心父表的配置問題。 只需使用 DataGrid 控制項的標準介面即可。 顯示相關資料的任何子網格都可以動態建立,並可以顯示在主網路的布局內部。



圖 2 嵌入式子 DataGrid

另一方面,需要提醒的是,設計 DataGrid 控制項不是為了包含分層資料。 其內部布局最適合顯示表格式資料。 DataList 控制項可能是一個不錯的選擇,但它不提供固有的分頁支援,並且需要一些代碼才能像 DataGrid 一樣工作。 當在 Google 上快速搜尋“嵌套 DataGrid”時,返回了討論如何將 DataGrid 嵌入到 DataList 控制項的文章的連結,這些文章給了我關於本專欄的一些啟示。 這裡,我將構造一個從 DataGrid 類繼承的自訂控制項。 該控制項實現一個自訂欄類型 (ExpandCommandColumn),並包含顯示與被單擊的項關聯的記錄所需的全部邏輯。 展開視圖通過嵌入到父級中的子 DataGrid 表示。 圖 2 顯示了此控制項的外觀。

構造嵌套網格

只有當資料來源是包含表之間的關係的 DataSet 對象時,分層的 DataGrid 控制項才有意義。 例如,假定某個 DataSet 具有 Customers 表和 Orders 表,並在 CustomerID 列上建立了這兩個表之間的 DataRelation。 只要 DataGrid 包含按鈕列,那麼當您單擊它時就能夠為選定的客戶建立一個子視圖,並將所產生的 DataView 對象綁定到子網格。

由於新控制項(在範例程式碼中稱為 NestedGrid)是從 DataGrid 類繼承的,因此可以在適合使用 DataGrid 對象的任何情況下使用它。 但是,最後這一句還有待修飾。 通常,當從基類派生控制項時,可能存在這樣的情況:所派生的控制項由於其特定的擴充和附加項而無法替換原始控制項。 在本專欄中,我不會花太多的時間來使 NestedGrid 組件向後相容基 DataGrid 類。 為了簡單起見,我假設您始終將它綁定到 DataSet 對象。

關於 NestedGrid 控制項,還有其他幾個假設,這將在後面的部分逐漸說明。 特別要說明的是,由您負責添加規定每一行的 expanded/collapsed 狀態的按鈕列。 從理論上來講,該列可以放在網格中的任何位置。 但是,我在這裡假設展開列是網格中的第一列。 (2003 年 8 月刊已討論,可以適當地修改行為,以便只有當 DataGrid 綁定到具有相關表的 DataSet 時才動態產生該列。)

如果您有過一點使用 DataGrid 控制項的經驗,會知道儘管它功能極其強大,可自訂性也非常強,但它無法很好地支援布局的變化。 網格布局表示表格式資料 — 按規則連續的若干個大小相等的行。 怎樣才能嵌入具有此限制的子網格呢?

這裡要提醒的重要一點是,網格是作為標準的 HTML 表呈現的。 一旦儲存格形成了規則的表布局,就可以在其中的每個儲存格中放入任何內容,其中包括表示子網格的子表(使用 rowspan 標記)。 首先,刪除包含命令按鈕的儲存格以外的其他所有儲存格,以修改組成選定行(即使用者單擊的展開命令按鈕所在的行)的儲存格的數目。 如果假設展開命令列位於最左側,這很容易實現。 所有儲存格都刪除後,可以建立一個橫跨若干列(列數必須等於 DataGrid 控制項的 Columns 集合中的項數)的全新儲存格。

此時,您已擁有了使該行可展開的完全自訂儲存格。 可以通過編程的方式在此自訂儲存格中填入伺服器控制項的任意組合。 例如,可以插入這樣一個表:最上面一行類比已刪除的儲存格的結構(通常是關於父行的資訊),最下面一行包含子 DataGrid。 圖 2 中的控制項是基於此方案建立的。

NestedGrid 類

前面已提到,NestedGrid 類從 System.Web.DataGrid 類繼承,並添加了額外幾個屬性(見圖 3)。 此控制項還將在需要資料繫結時引發自訂的 UpdateView 事件。 要對分配給 DataSource 屬性的物件類型加以嚴格的控制(並確保它是 DataSet),可以重寫 DataSource 屬性,如下面的代碼所示:

public override object DataSource
{
get {return base.DataSource;}
set {
if (!(value is DataSet)) {
// throw an exception
}
base.DataSource = value;
}
}

當使用者單擊行按鈕以展開記錄(某個客戶)查看其詳細資料時,NestedGrid 控制項執行個體化。 為此,嵌套的網格必須包含一個具有某些特定功能的按鈕列。 首先,網格必須提供針對 ItemCommand 事件的處理常式,以便可以處理展開/摺疊請求。 處理常式將 ExpandedItemIndex 屬性設定為被單擊的記錄的基於零的索引,並更新網格視圖。 那麼,什麼時候修改被單擊的行的布局合適呢?

網格布局建立出來後,ItemDataBound 事件在事件鏈的底部激發。 ItemDataBound 激發後,資料繫結階段基本完成,所有儲存格都可以顯示了。 此後您所看到的布局和資料將不會再發生任何變化。 就是因為這個原因,我決定在處理 ItemDataBound 事件之前實現所有必要的更改。

在深入探討控制項的實現之前,還有幾點注意事項需要提出來。 首先,ExpandedItemIndex 屬性是基於零的,但它表示的是所單擊的行的絕對位置。 此屬性與類似的網格屬性(如 SelectedItemIndex 和 EditItemIndex)的唯一不同之處在於,它表示的不是基於頁的值。 其次,NestedGrid 還在內部實現分頁。 要使該控制項在成員表的各頁之間移動,除了處理 UpdateView 事件並傳遞綁定資料以外,不必做其他任何工作:

void UpdateView(object sender, EventArgs e) {
BindData();
}
void BindData() {
dataGrid.DataSource = (DataSet) Cache["MyData"];
dataGrid.DataBind();
}

NestedGrid 類具有針對 PageIndexChanged 事件的內建處理常式,如下所示:

void PageIndexChanged(object sender, DataGridPageChangedEventArgs e)
{
CurrentPageIndex = e.NewPageIndex;
SelectedIndex = -1;
EditItemIndex = -1;
ExpandedItemIndex = -1;

if (UpdateView != null)
UpdateView(this, EventArgs.Empty);
}

NestedGrid 控制項的結構的關鍵要素是按鈕列。 為簡單起見,此版本的控制項僅支援單個展開項。 通過將 ExpandedItemIndex 屬性從整數更改為數組或集合,可以輕鬆地擴充此功能。

ExpandCommandColumn 類

可以使用字串(如“+/-”或“Expand/Collapse”)或位元影像來呈現展開列。 您可能要對不同的應用程式使用不同的圖片。 要實現此功能,最靈活的方法是使用幾個像 ExpandText 和 CollapseText 這樣的屬性。 那麼,應當在 NestedGrid 類上定義這些屬性嗎? 在類似的方案(就地編輯)中,ASP.NET 開發小組建立了一個自訂的 DataGrid 列,並在該列中放入了像 EditText、CancelText 和 UpdateText 這樣的屬性。 基於此,我建立了自己的 ExpandCommandColumn 類,並在其中放入了幾個文字屬性,以表示用於展開和摺疊視圖的 HTML 輸出。 下面的程式碼片段顯示了如何將該自訂欄與網格整合。

<cc1:NestedDataGrid id="dataGrid" runat="server" ...>
<Columns>
<cc1:ExpandCommandColumn
CollapseText="<img src=http://www.163design.net/a/s/images/collapse.gif>"
ExpandText=



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。