DropDownList 控制項常常會因為項目清單中不存在繫結的欄位,而發生以下的錯誤訊息。因為繫結資料的不完整或異常就會造成這樣的異常錯誤,在設計上實在是相當困擾,而且最麻煩的是這個錯誤在頁面的程式碼也無法使用 Try ... Catch 方式來略過錯誤。其實最簡單的方式就去直接去修改 DropDownList 控制項,讓 DropDownList 控制項繫結資料時,就算欄位值不存在清單項目中也不要釋出錯誤,本文就要說明如何繼承 DorpDownList 下來修改,來有效解決這個問題。
DropDownList 控制項常常會因為項目清單中不存在繫結的欄位,而發生以下的錯誤訊息。因為繫結資料的不完整或異常就會造成這樣的異常錯誤,在設計上實在是相當困擾,而且最麻煩的是這個錯誤在頁面的程式碼也無法使用 Try ... Catch 方式來略過錯誤。其實最簡單的方式就去直接去修改 DropDownList 控制項,讓 DropDownList 控制項繫結資料時,就算欄位值不存在清單項目中也不要釋出錯誤,本文就要說明如何繼承 DorpDownList 下來修改,來有效解決這個問題。
程式碼下載:ASP.NET Server Control - Day22.rar
Northwnd 資料庫下載:NORTHWND.rar
一、覆寫 SelectedValue 屬性解決資料繫結的問題
DropDownList 控制項繫結錯誤的原因,可以由上圖的錯誤訊息可以大概得知是寫入 SelectedValue 屬性時發生的錯誤;所以我們繼承 DorpDownList 下來命名為 TBDropDownList,並覆寫 SelectedValue 屬性來解決這個問題。解決方式是在寫入 SelectedValue 屬性時,先判斷準備寫入的值是否存在項目清單中,存在的話才寫入 SelectedValue 屬性,若不存在則直接設定 SelectedIndex 屬性為 -1。
Public Class TBDropDownList
Inherits DropDownList
''' <summary>
''' 覆寫 SelectedValue 屬性。
''' </summary>
Public Overrides Property SelectedValue() As String
Get
Return MyBase.SelectedValue
End Get
Set(ByVal value As String)
Dim oItem As ListItem = Me.Items.FindByValue(value)
If (oItem Is Nothing) Then
Me.SelectedIndex = -1 '當 Items 不存在時
Exit Property
Else
MyBase.SelectedValue = value
End If
End Set
End Property
End Class
我們以 Northwnd 資料庫的 Products 資料表做為測試資料,事先定義 DropDownList 的 Items 內容,其中第一個加入 "未對應" 的項目,將 SelectedValue 屬性繫結至 CategoryID 欄位。
<bee:TBDropDownList ID="DropDownList1" runat="server"
SelectedValue='<%# Bind("CategoryID") %>'>
<asp:ListItem Value="">未對應</asp:ListItem>
<asp:ListItem Value="2">Condiments</asp:ListItem>
<asp:ListItem Value="3">Confections</asp:ListItem>
</bee:TBDropDownList>
當資料的 CategoryID 欄位值不存在於 DropDownList 的 Items 集合屬性中時,就會顯示第一個 "未對應" 的項目。
二、TBDropDownList 設定 DataSoruceID 產生的問題
上述的解決方法在筆者的「讓 DropDownList DataBind 不再發生錯誤」一文中已經有提及,不過有讀者發現另一個問題,就是當 DropDownList 設定 DataSourceID 時卻會發生資料無法正常繫結,以下就來解決這個問題。
我們設定 TBDropDownList 的 DataSoruceID 來取得項目清單的內容,將 DataSourceID 設定為另一個取得 Categories 資料表內容的 SqlDataSource 控制項。
<bee:TBDropDownList ID="DropDownList1" runat="server"
SelectedValue='<%# Bind("CategoryID") %>' DataSourceID="SqlDataSource2"
DataTextField="CategoryName" DataValueField="CategoryID">
</bee:TBDropDownList>
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwnd %>"
SelectCommand="SELECT CategoryID, CategoryName, Description, Picture FROM Categories"
ProviderName="<%$ ConnectionStrings:Northwnd.ProviderName %>" >
</asp:SqlDataSource>
當執行程式時,FormView 原本在瀏覽模式時的 CategoryID 欄位值為 7 (CategoryName 應為 Product)。
當按下「編輯」時切換到 EditItemTemplate 時,改用 TBDropDownList 繫結 CategoryID 欄位值,可以這時欲無法繫結正確的值。
三、解決 TBDropDownList 設定 DataSourceID 造成資料無法繫結的問題
要解決上述 TBDropDownList 設定 DataSourceID 問題,需在設定 SelectedValue 屬性時,若 Items.Count=0 先用一個 FCachedSelectedValue 變數將正確的值先暫存下來,然後覆寫 PerformDataBinding 方法,當 DorpDownList 取得 DataSoruceID 所對應的項目清單內容後,因為這時 Items 的內容才會完整取回,再去設定一次 SelectedValue 屬性就可以正確的繫結資料。
Public Class TBDropDownList
Inherits DropDownList
Private FCachedSelectedValue As String
''' <summary>
''' 覆寫 SelectedValue 屬性。
''' </summary>
Public Overrides Property SelectedValue() As String
Get
Return MyBase.SelectedValue
End Get
Set(ByVal value As String)
If Me.Items.Count <> 0 Then
Dim oItem As ListItem = Me.Items.FindByValue(value)
If (oItem Is Nothing) Then
Me.SelectedIndex = -1 '當 Items 不存在時
Else
MyBase.SelectedValue = value
End If
Else
FCachedSelectedValue = value
End If
End Set
End Property
Protected Overrides Sub PerformDataBinding(ByVal data As System.Collections.IEnumerable)
MyBase.PerformDataBinding(data)
'DataSoruceID 資料繫結後再設定 SelectedValue 屬性值
If (Not FCachedSelectedValue Is Nothing) Then
Me.SelectedValue = FCachedSelectedValue
End If
End Sub
End Class
重新執行程式,切換到編輯模式時,TBDropDownList 就可以正確的繫結欄位值了。
備註:本文同步發佈於「第一屆iT邦幫忙鐵人賽」,如果你覺得這篇文章對您有幫助,記得連上去推鑒此文增加人氣 ^^
http://ithelp.ithome.com.tw/question/10012909
http://ithelp.ithome.com.tw/question/10012915