代码改变世界

ASP.NET DEMO Ⅳ : 使用数据源控件将数据绑定到 ListControl 上

2007-05-31 23:30  晓风残月  阅读(...)  评论(... 编辑 收藏

目的:

1. 展示 ListControl.AppendDataBoundItems 属性用法

2. 展示使用数据源控件绑定联动 ListControl

3.出发点:

      a. 今天 csdn 还有网友问,DropDownList 绑定数据后能否插入额外项?答案当然是肯定的。

      b. 昨天 forums.asp.net中有人使用数据源控件绑定两个联动DRP,设置第二个DRPAppendDataBoundItems=true,绑定数据后将出现重复数据。

      c. 自己学习下数据源绑定控件——用ASP.NET 2.0 一年了,基本还没实践性的操练过数据源控件,总存有疑虑——如此,傻瓜式的东东能上得了台面?

提示:

1. ASP.NET 2.0 为列表型控件基类 ListControl 提供了AppendDataBoundItems 属性,该值指示是否在绑定数据之前清除已  存在的列表项。默认值为 false。然而,只要你设置 AppendDataBoundItems=true,无论何时执行数据绑定(首次加载或者回发页面),都不会清除原有数据,而是将绑定数据追加上去。因此,如果我们希望每次绑定数据,插入自己的静态项(如常见的“选择全部”),而且希望在任意位置插入,还是只有手动实现。如果使用数据源控件绑定数据,那么需要选择正确的插入静态项时机。下面我们将展示,数据源绑定控件和手动绑定如何加入自定义额外项。

关于这个问题,早期 scott 在他的blog上做了讨论:

ListControl.AppendDataBoundItems Property in ASP.NET 2.0

2. 继承自 ListControl  的控件包括 BulletedList, CheckBoxList, DropDownList, ListBox, RadioButtonList

所有这些控件用法基本一致,这里我们以 DropDownList (DRP)为例。

3.示例由两个DRP组成,第一个DRP数据来自Northwind的Categories表,第二个DRP展示当前选择的Category的Product。

4.数据源控件包括AccessDataSource, SqlDataSource,ObjectDataSource,XmlDataSource,提供访问不同类型的数据源,如数据库、XML 文件或中间层业务对象。这里我们选择使用SqlDataSource。常规用法,我们都很熟悉,使用配置数据源向导,一路鼠标+回车,数据库中数据就展示在我们面前。

然而,这里我们希望为Category下来框增加一项“Select All”,以便能列出所有的Product。该模型SQL是通常是这样实现的,即如果参数 @CategoryID IS NULL,我们就返回所有的Product

SELECT [ProductID], [ProductName] FROM [Products] WHERE (@CategoryID IS NULL OR [CategoryID] = @CategoryID)

因此,我们希望SqlDataSource的过滤参数(由Parameter 类的扩展类表示)能接受或者将某个预定值自动将转化为 DBNull,非常幸运,Parameter确实为我们提供了 ConvertEmptyStringToNull 属性以指示是否将空字符串转换为null。默认值为true。

然而,SqlDataSource还公开了一个开关项属性 CancelSelectOnNullParameter,该属性指示当 SqlDataSource的 SelectParameters 集合中包含任何一个参数为空引用时,是否取消数据检索操作。默认值为true。因此,为实现我们的示例,我们需要将其设置为false。

5.现在我们再来看下AppendDataBoundItems 的用法,首先设置 drpCategory.AppendDataBoundItems=True,然后手动添加了一个静态项,text="Select ALL" 而 value="",就像前面所述,SqlDataSource使用的过滤参数(这里是ControlParameter)会自动将其转换为null。

   1: <asp:DropDownList ID="drpCategory" runat="server" AppendDataBoundItems="True"
   2:             AutoPostBack="True" DataSourceID="dsCategory" DataTextField="CategoryName"
   3:             DataValueField="CategoryID">
   4:             <asp:ListItem Value="">Select All</asp:ListItem>
   5:         </asp:DropDownList>

对于drpProduct 呢?如果我们依葫芦画瓢:

   1: <asp:DropDownList ID="drpProduct" runat="server" DataSourceID="dsProduct" AppendDataBoundItems="true" 
   2:            DataTextField="ProductName" DataValueField="ProductID">
   3:            <asp:ListItem Value="">Please select a product</asp:ListItem>
   4:        </asp:DropDownList>

选择第二次选择Category后我们将得到重复的Product列表:

因此,我们只有另择他法。回忆 ASP.NET 1.x 我们是如何处理的呢?

   1: void drpCategory_SelectedIndexChagned(object sender, EventArgs e)
   2:    {
   3:        int selectedCategoryId = -1;
   4:        // ...
   5:        // 
   6:        drpProduct.DataSource = BindProductByCategory(selectedCategoryId);
   7:        drpProduct.DataBind();
   8:  
   9:        ListItem item = new ListItem("Please select a product", "");
  10:        drpProduct.Items.Insert(0, item);        
  11:    }

然而,由于我们将数据绑定完全委托给数据源控件处理,我们应该在哪里添加我们额外项呢?答案是 ListControl 的 DataBound 事件!该事件在执行数据绑定之后触发。

   1: void drpProduct_DataBound(object sender, EventArgs e)
   2:     {
   3:         ListItem item = new ListItem("Please select a product", "");
   4:         //drpProduct.Items.Add(item);
   5:         // u can insert the All item to Items at the specified index location,
   6:         // such as zero
   7:         drpProduct.Items.Insert(0, item);
   8:         // u can set the All as the selected item.
   9:         //drpProduct.SelectedIndex = drpProduct.Items.Count - 1; 
  10:     }

 完整代码:

   1: <%@ Page Language="C#" AutoEventWireup="true" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <script runat="server">
   1:  
   2:     void Page_Load(Object sender, EventArgs e)
   3:     {
   4:         
   5:     }
   6:  
   7:     void Page_PreRender(object sender, EventArgs e)
   8:     {
   9:         
  10:     }
  11:  
  12:     void drpProduct_DataBound(object sender, EventArgs e)
  13:     {
  14:         ListItem item = new ListItem("Please select a product", "");
  15:         //drpProduct.Items.Add(item);
  16:         // u can insert the All item to Items at the specified index location,
  17:         // such as zero
  18:         drpProduct.Items.Insert(0, item);
  19:         // u can set the All as the selected item.
  20:         //drpProduct.SelectedIndex = drpProduct.Items.Count - 1; 
  21:     }
  22:     
  23:     protected void dsProduct_Selected(object sender, SqlDataSourceStatusEventArgs e)
  24:     {
  25:  
  26:     }
</script>
   6:  
   7: <html xmlns="http://www.w3.org/1999/xhtml" >
   8: <head runat="server">
   9:     <title>活用 ListControl.AppendDataBoundItems 属性</title>
  10: </head>
  11: <body>
  12:     <form id="form1" runat="server">
  13:     <h2 style="text-align:center;">活用 ListControl.AppendDataBoundItems 属性</h2>    
  14:     <div>
  15:         Category:
  16:         <asp:DropDownList ID="drpCategory" runat="server" AppendDataBoundItems="True"
  17:             AutoPostBack="True" DataSourceID="dsCategory" DataTextField="CategoryName"
  18:             DataValueField="CategoryID">
  19:             <asp:ListItem Value="">Select All</asp:ListItem>
  20:         </asp:DropDownList>
  21:         <asp:SqlDataSource ID="dsCategory" runat="server" ConnectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True"
  22:             ProviderName="System.Data.SqlClient" SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories]">
  23:         </asp:SqlDataSource>
  24:         Product:
  25:         <asp:DropDownList ID="drpProduct" runat="server" DataSourceID="dsProduct" OnDataBound="drpProduct_DataBound" 
  26:             DataTextField="ProductName" DataValueField="ProductID">
  27:         </asp:DropDownList>
  28:         <asp:SqlDataSource ID="dsProduct" runat="server" ConnectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True"
  29:             ProviderName="System.Data.SqlClient" CancelSelectOnNullParameter="false" SelectCommand="SELECT [ProductID], [ProductName] FROM [Products] WHERE (@CategoryID IS NULL OR [CategoryID] = @CategoryID)" OnSelected="dsProduct_Selected">
  30:             <SelectParameters>
  31:                 <asp:ControlParameter ControlID="drpCategory" Name="CategoryID" ConvertEmptyStringToNull="true"
  32:                     PropertyName="SelectedValue" Type="Int32" />
  33:             </SelectParameters>
  34:         </asp:SqlDataSource>
  35:         <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="Please select a product" ControlToValidate="drpProduct" Display="Dynamic"></asp:RequiredFieldValidator>
  36:         <asp:Button ID="btnPostBackTest" Text="PostBack Test" runat="server" />
  37:     </div>
  38:     </form>
  39: </body>
  40: </html>
下载