技术总奸

Tip/Trick ASP.NET 2.0: DropDownList DataBind

问题

用DropDowList输入参照数据时,例如输入产品信息时,选择产品类别,通常情况下产品类别也应该是从数据库中绑定出来的。这时会用两个问题:

  1. 如何方便的在DropDownList里放入一个空值,即Value为空字符串的一个ListItem,因为数据源中是不存在空值的;
  2. 当编辑某个产品信息时,如果该条产品信息的类别信息已经删除,那么在编辑视图绑定数据时,DropDownList就会报错,因为此时DropDownList的Items集合中 并不存在值为SelectedValue的Item。其实这是个数据一致性的问题。

办法

解决问题1需要利用DropDownList的AppendDataBoundItems属性,这个属性在ASP.NET 1.x是好像是没有的,所以在2.0中一直也没注意到,直到一天才偶然发现。顾名思义,这个属性的作用就是把绑定产生的Items附加到原有Items的后面。那么,解决问题1,我们就可以先在页面里显性声明一个静态的ListItem,如:<asp:ListItem Value="">None</asp:ListItem>,然后将DropDownList的AppendDataBoundItems属性设为true(默认值为false),完整代码实例看下方。

解决问题2,需要对DropDownList做一些必要的扩展,因为在问题2所处的情况下,DropDownList的默认行为就是抛出一个异常,我们的目的是使其具有"容错"功能,在SelectedValue不存在的情况下,默认选择第一项,也就是空值项。通过对DropDownList源码的研究,我们发现这个异常是在执行PerformDataBinding 方法时抛出的,那么最简单的方法就是重写改方法,吃掉抛出的异常,代码片段见下方。

aspx代码片段:
            <asp:FormView ID="FormViewProductDetail" runat="server" DataKeyNames="PurchaseOrderID"
                DataSourceID="SqlDataSourceProduct" Width="100%">
                <EditItemTemplate>
                    <table cellpadding="0" cellspacing="0" width="100%" border="0">
                        <tbody>
                            <tr class="alternating">
                                <td>
                                    <asp:Label ID="Label1" runat="server" Text="Product Name"></asp:Label>
                                </td>
                                <td>
                                    <asp:TextBox ID="ProductNameTextBox" runat="server" Text='<%# Bind("ProductName") %>'>
                                    </asp:TextBox>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <asp:Label ID="Label8" runat="server" Text="Category"></asp:Label></td>
                                <td>
                                    <ts:DropDownList ID="DropDownListCategory" runat="server" AppendDataBoundItems="True"
                                        DataSourceID="SqlDataSource1" SelectedValue='<%# Bind("CategoryID") %>' DataTextField="CategoryName"
                                        DataValueField="CategoryID">
                                        <asp:ListItem Value="">None</asp:ListItem>
                                    </ts:DropDownList>
                                    <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:MyConnectionString %>"
                                        SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Category]"></asp:SqlDataSource>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </EditItemTemplate>
                ......Other Template.........
            </asp:FormView>


DropDownList扩展:
    public class DropDownList : System.Web.UI.WebControls.DropDownList
    {
        /// 

        /// kill the exception. the exception was raised because the selectedvalue does not exist in the list items, 

        /// we do not hope the control throws a "selectedvalue not exist..." exception

        /// 

        /// 

        protected override void PerformDataBinding(System.Collections.IEnumerable dataSource)

        {

            try

            {

                base.PerformDataBinding(dataSource);

            }

            catch (ArgumentOutOfRangeException ex)

            {

                ArgumentOutOfRangeException o = ex;

            }

        }

    }

posted on 2005-01-01 00:00  阿福  阅读(66)  评论(0编辑  收藏  举报