玩转C科技.NET

从学会做人开始认识这个世界!http://volnet.github.io

导航

小程序大问题,MSDN中一个小小示例所带来的疑问,一个关于DataList的一个简单应用

今天在做MSDN中的一个关于DataList中的一个简单的例子,(MSDN中的地址为ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vwdcon/html/6c9b75c9-67c1-46e1-b0ad-993a2ca6f8e7.htm)

首先声明这是一个简单的例子,只是为了个人收藏吧。

关于MSDN的例子,在这里就不再多描述了。就对自己发现的几个问题做一个简单的记录。

对示例的看法:

优点:

例子给人的第一印象还是很不错的,通过简单的对ItemTemplate的简单编辑用于显示Northwind中表的信息,相信对DataList的入门大有好处,至于使用SqlDataSource控件进行数据源绑定所产生的不可复用性与本示例无关,因此所谓模式上的东西在这里没有必要拿来做对比,只能说本示例只为了表达关于DataList's ItemTemplate的一些用法。

缺点:

示例中多次复用相同变量的值让人很难把握前后台之间控件的交互关系。至少我是看闷了,而且对方法DataBinder.Eval(object container, string expression)以及SqlDataSource.SelectParameter[string name]的解释都让人很难有想像力。至少我看完以后没明白究竟它们是在干嘛。

附录:(来自MSDN)

下面将DataBinder.Eval以及SelectParameter的方法含义做一点摘抄,让您有所"了解"。

public static Object Eval (

    Object container,

    string expression

)

参数

container

表达式根据其进行计算的对象引用。此标识符必须是以页的指定语言表示的有效对象标识符。

 

expression

从 container 到要放置在绑定控件属性中的公共属性值的导航路径。此路径必须是以点分隔的属性或字段名称字符串,如 C# 中的 "Tables[0].DefaultView.[0].Price" 或 Visual Basic 中的 "Tables(0).DefaultView.(0).Price"。

SqlDataSource.SelectParameter

从与 SqlDataSource 控件相关联的 SqlDataSourceView 对象获取包含 SelectCommand 属性所使用的参数的参数集合。

 

 

下面不再废话,就在这个让人一晕一晕的程序上把问题给解释了吧。

先给出示例中的程序:

ASPX页面

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WA_FormatDataList._Default" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>FormatDataList</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:DataList ID="DataList1" runat="server" DataSourceID="SqlDataSource1" OnItemDataBound="DataList1_ItemDataBound">

<ItemTemplate>

CategoryName:

<asp:Label ID="CategoryNameLabel" runat="server" Text='<%# Eval("CategoryName") %>' Font-Bold="True"></asp:Label>&nbsp; (CategoryID:

<asp:Label ID="CategoryIDLabel" runat="server" Text='<%# Eval("CategoryID") %>'>

</asp:Label>

)<br />

<br />

<asp:BulletedList ID="BulletedList1" runat="server" DataSourceID="bulletedListDataSource"

DataTextField="ProductName" DataValueField="ProductName">

</asp:BulletedList>

<asp:SqlDataSource ID="bulletedListDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"

SelectCommand="SELECT [ProductName] FROM [Products] WHERE ([CategoryID] = @CategoryID)">

<SelectParameters>

<asp:Parameter Name="CategoryID" Type="Int32" />

</SelectParameters>

</asp:SqlDataSource>

</ItemTemplate>

<SeparatorTemplate>

<hr />

</SeparatorTemplate>

</asp:DataList><asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"

SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Alphabetical list of products]">

</asp:SqlDataSource>

 

</div>

</form>

</body>

</html>

CS代码部分

……

protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)

{

if (e.Item.ItemType == ListItemType.Item ||

e.Item.ItemType == ListItemType.AlternatingItem)

{

SqlDataSource ds;

ds = e.Item.FindControl("bulletedListDataSource") as SqlDataSource;

ds.SelectParameters["CategoryID"].DefaultValue

= DataBinder.Eval(e.Item.DataItem, "categoryid").ToString();

}

}

……

注意:本程序中多处出现CategoryID,categoryid,这让人很难理解程序是如何工作的,为此,我特地对这个程序的部分命名做了修改,让我们解释程序的时候更加地轻松。

[两块代码仅有"水红"色部分不同]

ASPX页面,修改部分用"水红"色来表示

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WA_FormatDataList._Default" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>FormatDataList</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:DataList ID="DataList1" runat="server" DataSourceID="SqlDataSource1" OnItemDataBound="DataList1_ItemDataBound">

<ItemTemplate>

CategoryName:

<asp:Label ID="CategoryNameLabel" runat="server" Text='<%# Eval("CategoryName") %>' Font-Bold="True"></asp:Label>&nbsp; (CategoryID:

<asp:Label ID="CategoryIDLabel" runat="server" Text='<%# Eval("myCategoryID") %>'>

</asp:Label>

)<br />

<br />

<asp:BulletedList ID="BulletedList1" runat="server" DataSourceID="bulletedListDataSource"

DataTextField="ProductName" DataValueField="ProductName">

</asp:BulletedList>

<asp:SqlDataSource ID="bulletedListDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"

SelectCommand="SELECT [ProductName] FROM [Products] WHERE ([CategoryID] = @TestCategoryID)">

<SelectParameters>

<asp:Parameter Name="TestCategoryID" Type="Int32" />

</SelectParameters>

</asp:SqlDataSource>

</ItemTemplate>

<SeparatorTemplate>

<hr />

</SeparatorTemplate>

</asp:DataList><asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"

SelectCommand="SELECT [CategoryID] as myCategoryID, [CategoryName] FROM [Alphabetical list of products]">

</asp:SqlDataSource>

 

</div>

</form>

</body>

</html>

CS代码部分,修改部分用"水红"色来表示

……

protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)

{

if (e.Item.ItemType == ListItemType.Item ||

e.Item.ItemType == ListItemType.AlternatingItem)

{

SqlDataSource ds;

ds = e.Item.FindControl("bulletedListDataSource") as SqlDataSource;

ds.SelectParameters["TestCategoryID"].DefaultValue

= DataBinder.Eval(e.Item.DataItem, "mycategoryid").ToString();

}

}

……

下面让我们来解释一下程序的运行,进而分析出那些让人头晕的函数是如何有机地工作的。

我们知道DataList控件在显示的时候是通过ItemTemplate中所做的一些设置来绑定数据,并作显示的,而这个项模板在绑定数据的时候就激发了ItemDataBound事件。

在本示例中(看ASPX部分的代码)在<ItemTemplate></ItemTemplate>之间我们定义了它的一些绑定(这些可以通过"编辑模板"或直接"书写代码"来完成)。其中有两个Label控件用于绑定数据,可是我们是如何知道数据的内容的呢?由于在DataList的定义标记内发现了DataSourceID = "SqlDataSource1"的一个数据源,而该数据源通过了SelectCommand="SELECT [CategoryID] as myCategoryID, [CategoryName] FROM [Alphabetical list of products]">命令从数据库中得到了一个虚拟的表,可以想像是一张含有两列的表,表中充满了对应的数据。而在<ItemTemplate>中我们就是通过Eval("myCategroyID")和Eval("CategoryName")来将这张虚构的表绑定到两个Label上的,它们正是这两个Label的Text属性。[之前未添加as myCategoryID的时候你很难理解那两个数据的来源,而我们知道用as的语法,我们从数据库中得到的虚表的对应列将被重命名为myCategoryID,这样我们就能明白这是绑定那张表的实质,而这在之前简直没有说服力。不知道的还以为直接从数据库中读的数据,而其中还包含了数据源的概念。]

在这个示例的最初我们只做了如上的两个绑定,因此绑定看起来还相对比较简单,下面我们将扩展这样一个内容,我们从以上得到的数据中去取得对应的CategoryID值作为Where子句的查询条件,去另一张表(这里是Products表)中查找对应Where子句条件的相应值(这里是ProductName)。(详见:SelectCommand="SELECT [ProductName] FROM [Products] WHERE ([CategoryID] = @TestCategoryID)")下面问题又来了,注意到我们用了一个新的数据源专门为控件bulletedList服务,取名为bulletedListDataSource,它执行了以上的T-SQL语句,准备从数据库中获得满足对应条件WHERE ([CategoryID] = @TestCategoryID)的值。而其实参数(@TestCategoryID)在被初始化的时候并不知道自己是什么!但是很高兴我们在数据绑定的时候激发了事件ItemDataBound,下面我们可以利用这个事件,让我们得到数据源bulletedListDataSource中SelectCommand中所需要的参数的值,我们的参数名称是@后面的TestCategoryID,它的值应该等于与之对应的ID = CategoryIDLabel的控件所标识的值myCategoryID,这里唯一不明确的是这个myCategoryID究竟是之前CategoryIDLabel控件的值呢,还是赋值给CategoryIDLabel控件的表呢?[以下内容有点牵强,请高手鉴定]其实这里应该是表,也就是数据源提供的虚表,我们注意到e.Item.DataItem,也许我们还是不理解究竟它是个什么东西,但我们可以这么去理解它,通过MSDN给您的提示,你应该注意到它是一个object container,而expression则是"从 container 到要放置在绑定控件属性中的公共属性值的导航路径",对于导航路径您或许有和我一样的疑惑,没关系继续看,后面写着的简单示例告诉我们它和Tables有关,我们可以猜测它应该是来自表的。另外你还可以通过断点调试来告诉自己e.Item.DataItem = {System.Data.DataRowView},它是一个数据行的视图,之后我们通过这个视图去寻找这个名字叫mycategoryid的列的内容,就可以让当前的参数有值并唯一地确定了那个参数,并将后来的<SelectParameter></SelectParameter>中的参数给赋值(实现代码在CS文件中)。另外你还可以通过大小写来判断它是来自虚表(View/视图)而不是从那个控件中获得。因为我们知道数据库中的表是不区分大小写的!

至此,这个程序完成了将数据绑定的全过程,怎么样?这样小小的一个程序是不是也隐藏着重重危机呢?也许你已经习惯于这些控件的使用,对其中的缘由不再关心,甚至两年前你就封装好了一个控件,只要提供一条SQL语句就能够正确的为所欲为,也许,我想知其然还要知其所以然才能够在Programing的时代长足发展。

posted on 2007-03-09 08:35  volnet(可以叫我大V)  阅读(2721)  评论(3编辑  收藏  举报

使用Live Messenger联系我
关闭