iT邦幫忙

DAY 24
15

ASP.NET 伺服器控制項開發系列 第 29

[ASP.NET 控制項實作 Day24] TBDropDownField 的 Items 屬性的資料繫結

上篇中我們實作了 GridView 的 TBDropDownField 欄位類別,不過眼尖的讀者不知有沒有發覺我們並處理 Items 屬性取得成員清單的動作,而是直接設定儲存格內含的 TBDropDownList 控制項相關屬性 (DataSourceID、DataTextField、DataValueField 屬性) 後,就由 TDropDownList 控制項自行處理 Items 屬性的資料繫結。當 GridView 的資料列是編輯狀態時,下拉清單會顯示出 Items 的文字內容;可是瀏覽狀態的資料列,卻是顯示欄位原始值,無法呈現 Items 的文字內容。本文將說明如何自行處理 TBDropDownField 的 Items 屬性的資料繫結動作,並使唯讀狀態的資料列也可以呈現 Items 的文字內容。

程式碼下載:ASP.NET Server Control - Day24.rar
Northwnd 資料庫下載:NORTHWND.rar

一、Items 屬性的問題
我們重新看一次原本 TBDropDownField 類別在處理 Items 屬性的資料繫結取得清單內容的程式碼,在覆寫 InitializeDataCell 方法中,當儲存格為編輯模式時,會呈現 TBDropDownList 控制項並設定取得 Items 清單內容的相關屬性,讓 TBDropDownList 自行去處理它的 Items 屬性的清單內容。

'由資料來源控制項取得清單項目
oDropDownList.DataSourceID = Me.DataSourceID
oDropDownList.DataTextField = Me.DataTextField
oDropDownList.DataValueField = Me.DataValueField

不知你有沒有發覺,我們無論在 InitializeDataCell 及 OnDataBindField 方法中,都沒有針對 TBDropDownList 控制項做任何 DataBind 動作,那它是怎麼從 DataSourceID 關聯的資料來源擷取資料呢?因為 GridView 在執行 DataBind 時,就會要求所有的子控制項做 DataBind,所以我們只要設定好 BDropDownList 控制項相關屬性後,當 TBDropDownList 自動被要求資料繫結時就會取得 Items 的清單內容。
當然使用 TBDropDownList 控制項去處理 Items 的資料繫結動作最簡單,可是這樣唯讀的儲存格只能顯示原始欄位值,無法呈現 Items 中對應成員的文字;除非無論唯讀或編輯狀態,都要建立 TBDropDownList 控制項去取得 Items 清單內容,而唯讀欄位使用 TBDropDownList.Items 去找到對應成員的顯示文字,不過這樣的作法會怪怪的,而且沒有執行效能率。所以比較好的辨法,就是由 TBDropDownField 類別自行處理 Items 的資料繫結,同時提供給唯讀狀態的
DataControlFieldCell 及編輯狀態的 TBDropDownList 使用。

二、由 TBDropDownField 類別處理 Items 屬性的資料繫結
我們要自行處理 Items 屬性來取得成員清單,在 InitializeDataCell 方法中無須處理 Items 屬性,只需產生儲存格需要的子控制項,未來在執行子控制項的 DataBinding 時的 OnDataBindField 方法中再來處理 Items 屬性。

        Protected Overrides Sub InitializeDataCell( _
            ByVal Cell As DataControlFieldCell, _
            ByVal RowState As DataControlRowState)

            Dim oDropDownList As TBDropDownList
            Dim oControl As Control

            If Me.CellIsEdit(RowState) Then
                oDropDownList = New TBDropDownList()
                oControl = oDropDownList
                Cell.Controls.Add(oControl)
            Else
                oControl = Cell
            End If

            If (oControl IsNot Nothing) AndAlso MyBase.Visible Then
                AddHandler oControl.DataBinding, New EventHandler(AddressOf Me.OnDataBindField)
            End If
        End Sub

在 OnDataBindField 方法中,我們加上一段處理 Items 屬性的程式碼如下,會利用 PerformSelecrt 私有方法,由關聯的資料來源 (即 DataSrouceID 指定的資料來源控制項) 擷取資料並產生 Items 的成員清單,在後面會詳細講解 PerformSelecrt 方法處理擷取資料的細節。因為 TBDropDownField 每個資料儲存格都會執行 OnDataBindField 方法,但 Items 取得成員清單的動作只需做一次即可,所以會以 FIsPerformSelect 區域變數來判斷是否已取得 Items 的成員清單,若已取過就不重新取得,這樣比較有執行效能。

            If Not Me.DesignMode Then
                If Not FIsPerformSelect Then
                    '從關聯的資料來源擷取資料
                    PerformSelect()
                    FIsPerformSelect = True
                End If
            End If

當取得儲存儲的對應的欄位值時,依此欄位值由 Items 集合去取得對應的 ListItem 成員,並以此 ListItem.Text 的文字內容來做顯示。

            '由 Items 去取得對應成員的顯示內容
            oListItem = Me.Items.FindByValue(CCStr(sText))
            If oListItem IsNot Nothing Then
                sText = oListItem.Text
            End If

若是由 TBDropDownList 所引發的 OnDataBindField 方法時,使用 SetItems 私有方法將 TBDropDownField.Items 屬性複製給 TBDropDownList.Item 屬性。

                ODropDownList = DirectCast(oControl, TBDropDownList)
                SetItems(ODropDownList)

SetItems 私有方法的程式碼如下。

        Private Sub SetItems(ByVal DropDownList As TBDropDownList)
            Dim oItems() As ListItem

            If Not Me.DesignMode Then
                ReDim oItems(Me.Items.Count - 1)
                Me.Items.CopyTo(oItems, 0)
                DropDownList.Items.AddRange(oItems)
            End If
        End Sub

[超過字數限制,下一篇接續本文]

備註:本文同步發佈於筆者「ASP.NET 魔法學院」部落格
http://www.dotblogs.com.tw/jeff377/archive/2008/10/25/5772.aspx


上一篇
[ASP.NET 控制項實作 Day23] 自訂GridVie欄位-實作TBDropDownField欄位(續3)
下一篇
[ASP.NET 控制項實作 Day24] TBDropDownField 的 Items 屬性的資料繫結(續)
系列文
ASP.NET 伺服器控制項開發40

尚未有邦友留言

立即登入留言