DropDownList 控件常常会因为项目清单中不存在系结的字段,而发生以下的错误讯息。因为系结数据的不完整或异常就会造成这样的异常错误,在设计上实在是相当困扰,而且最麻烦的是这个错误在页面的程序代码也无法使用 Try ... Catch 方式来略过错误。其实最简单的方式就去直接去修改 DropDownList 控件,让 DropDownList 控件系结数据时,就算字段值不存在清单项目中也不要释出错误,本文就要说明如何继承 DorpDownList 下来修改,来有效解决这个问题。

image

程序代码下载: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 集合属性中时,就会显示第一个 "未对应" 的项目。

image

 

二、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)。

image

image

 

当按下「编辑」时切换到 EditItemTemplate 时,改用 TBDropDownList 系结 CategoryID 字段值,可以这时欲无法系结正确的值。

image

 

三、解决 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 就可以正确的系结字段值了。

image

 

备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10012909
http://ithelp.ithome.com.tw/question/10012915

posted on 2008-10-23 07:20  jeff377  阅读(2141)  评论(6编辑  收藏  举报