首页 > 编程 > .NET > 正文

ASP.NET 2.0打造购物车和支付系统之一

2024-07-10 13:06:05
字体:
来源:转载
供稿:网友

到目前为止,我几乎在每一个我参加过的商业c#.net工程中使用了datagrid控件;因此,当我第一次听到有关于gridview是如何提高工作效率时,我飞快地试用了它。datagrid和gridview都是asp.net 2.0中提供的新的控件类,它们允许你快速容易地显示表格式数据;并且当在线观看它们时,它们都能被转换为客户端html表格进行显示。

  一. 简介

  这是系列文章的第一篇。在本篇中,我们将通过一个简单的网上商店示例程序来集中讨论gridview控件的一些用法。注意,在每一篇文章中我们都使用相同的源文件。为了观察本文示例演示效果,你只需要把下载内容解压到你的web服务器上一个新的目录并浏览到该目录名即可。例如,如果你把所有的内容解压到一个你的web服务器根目录下的目录"gridviewshop",并导航到这个目录:
http://www.yourserver.com/gridviewshop

  如果一切顺利,那么你应该会看到一个如下图1所示的站点:



图1.本系列文章网上商店演示程序快照。

  二. gridview

  如果你已经使用datagrid实现了你的系统,包括你自己的定制分页与排序方案,那么,你真正不需要考虑更新到gridview;因为从终端效果来看,它们都生成相同的内容(都生成一个html表格)。然而,如果你刚开始开发一个新的系统,那么,我建议你使用gridview,特别是如果你想利用它内置的分页与排序功能的话。

  通过在设计时刻设置各种属性,你可以控制gridview从外观到功能等若干方面。在本系列文章后面,我们将会更为深入地探讨这些方面,通过把一些css类指派给表格行和表格列头;当然,还要添加一些事件处理器以便允许用户与每一行数据进行交互。

  填充gridview类似于填充一个datagrid。你只需创建datasource,然后使用如下代码把它绑定到gridview即可:

mygridview.datasource = yourdatasource;
mygridview.databind();

  当然,借助于.net 2.0,你还有另一种选择,那就是创建一个sqldatasource并把gridview直接绑定到其上。这是通过设置它的datasourceid以匹配你指派给sqldatasource的id实现的,即是:

<!--使用mysqldatasource的id创建sqldatasource-->
<asp:sqldatasource
id="mysqldatasource"
runat="server"
datasourcemode="datareader"
connectionstring="<%$ connectionstrings:mynorthwind%>"
selectcommand="select lastname from employees">
</asp:sqldatasource>
<!--创建gridview并且指派它的datasourceid以匹配上面的mysqldatasource-->
<asp:gridview
id="mygridview"
runat="server"
autogeneratecolumns="true"
datasourceid="mysqldatasource"/>

  作为个人,我并不太看重这种方法,尽管它是微软推荐的建立你的gridview的方法。我比较喜欢更多地控制我的datasource;因为,这样以来我能够手工过滤它的内容甚至更多,这也正是为什么我在这个商店演示程序中没有使用这个方法的原因。

  好,下面让我们继续讨论构建本文中的商店演示程序。其大致情况是,在一个页面上存在两个gridviews;你在前面已经看到这个图像。一个gridview用于显示我们的商店的产品,而其它的内容对应于购物篮。你能够容易地把这两部分拆分到它们各自的页面中,但是为了简化起见,我们把这些内容放到了一起。

  如果你打开default.aspx(它包括在本文相应的zip源码文件中),你能够看到这个页面是如何建立的。大多数html仅仅用于实现包装之目的;需要注意的是,位于页面顶部的声明以及主<form>标签和位于其内的<gridview>标签。

  三. 页面声明

<%@ page inherits="shop.site" src="cs/site.aspx.cs" %>

  该页面声明简单地告诉我们的页面它属于什么命名空间和类。在这个例子中,我们的命名空间是"shop"而我们的类是"site"。还存在一个称为"src"的额外属性定义,它指向包含该站点类的普通的.cs文本文件。

  我通常在开发期间,把我的类放在外部.cs文件中,并把它们手工地编译成.dll文件。当我使用visual studio时,在开发期间,我总是习惯使用预编译的dll,因为稍后,只需要一个简单的构建即可以生成它们。一旦我完成了相应的工作,我都会把该类构建成预编译的dll;但是,在开发期间,我比较喜欢把较多的时间花费在编码方面而不是编译上。

四. 构建数据

<asp:gridview
id="gvbasket"
autogeneratecolumns="false"
showheader="true"
showfooter="true"
datakeynames="id"
onrowdatabound="gvbasket_rowdatabound"
runat="server">
<columns>
<asp:imagefield dataimageurlfield="thumb" alternatetext="product thumbnail" readonly="true" />
<asp:templatefield headertext="item">
<itemtemplate>
<h3><asp:literal id="lititemname" runat="server" /></h3>
</itemtemplate>
<footertemplate>
<a href="delivery-costs.aspx" title="view the list of delivery charges">delivery charges</a>
<br /><hr />
<b>total</b>
</footertemplate>
</asp:templatefield>
</columns>
</asp:gridview>

  如果你仔细地观察一下这两个gridviews,你会注意到它们都把autogeneratecolumns设置成false。如果没有这一行,或如果它被设置为true,那么,当我们绑定datasource时,我们的列就会被创建。通过关闭这个特征,我们能够使用"columns"子标签来定义自己的列。使用这一特征,我们能够创建许多不同类型的列。在这个演示程序中,我们使用了imagefield和templatefield列类型。该imagefield列把一个图像路径作为它的值(通过dataimageurlfield属性),然后在它自己的列内显示该图像(当生成到该页面时)。

  templatefield是真正重要的列。它允许你定义一个headertemplate,一个itemtemplate和一个footertemplate。这三个标签允许你把任何内容放到这些地方。其中,headertemplate和footertemplate都引用该列的页眉和页脚,而itemtemplate引用body内容。

  如果你观察一下购物篮gridview,你会看到我们已经使用itemtemplate来显示购物篮中每一项的名字,价格和数量;然后,我们在footertemplate内显示运送费用及总价。上面的片断仅显示"name"列和它的页脚;完整的实现,请参考default.aspx源文件。因为每一列的页眉都是静态文本,所以我们使用headertemplate跳过,并代之使用了templatefield的headertext属性。为了观察一个gridview的页眉和页脚,你必须把gridview的showheader和showfooter属性都设置为true。

  使用itemtemplate的另一个原因在于,你可以把其它html和.net标签放于其中。在这个演示程序中,存在若干不同的类型标签,包括<input>,
,<hr/>,<asp:literal>和<a>。把所有这些标签放到一个itemtemplate标签内的唯一问题是,你必须多做一些工作来预填充它们,但是并不需要太多工作。第一步是设置gridview的rowdatabound事件。你可以指派一个函数给这个事件(在我们绑定datasource后,在每次创建一行时,调用这个事件)。你可以在购物篮的gridview属性中看到这一点:
onrowdatabound="gvbasket_rowdatabound"

  相比之下,产品gridview相应的对应功能更简单些,但是它仅显示如何填充itemtemplate而不是header或footer模板。

  五. 一个重要的函数

  现在,让我们看一下本示例程序中位于"cs"文件夹下的主要的类文件"site.aspx.cs",并且定位到一个称为gvbasket_rowdatabound的函数。下面是该函数的主要实现(当然,你可以参考下载源码检查该文件的其它部分):

protected void gvbasket_rowdatabound(object sender, gridviewroweventargs e)
{
 switch( e.row.rowtype )
 {
  case datacontrolrowtype.datarow:
   //名称/描述
   ((literal)e.row.findcontrol("lititemname")).text = convert.tostring(((datarowview)e.row.dataitem)["name"]);
   //数量
   string quantity = convert.tostring(((datarowview)e.row.dataitem)["quantity"]);
((htmlinputtext)e.row.findcontrol("itproductquantity")).value = quantity;
   //价格
   ((literal)e.row.findcontrol("litprice")).text = string.format("{0:c2}", convert.todouble(((datarowview)e.row.dataitem)["price"]) * convert.toint32(quantity));
   break;
  case datacontrolrowtype.footer:
   datatable dtshop = getbasketdt();
   double total = 0.00;
   for(int i = 0; i < dtshop.rows.count; i++)
   {
    total += convert.toint32(dtshop.rows[i]["quantity"]) * convert.todouble(dtshop.rows[i]["price"]);
   }
   ((literal)e.row.findcontrol("littotalquantity")).text = convert.tostring(dtshop.compute("sum(quantity)", ""));
   ((literal)e.row.findcontrol("litdeliveryprice")).text = string.format("{0:c2}", convert.todouble(calcdeliverycost(total)));
   ((literal)e.row.findcontrol("littotalprice")).text = string.format("{0:c2}", convert.todouble(calcdeliverycost(total)) + total);
   break;
  }
}

  我们要做的第一件事是在rowtype属性上执行一个切换,这样我们就能够区别我们在填充一个header,footer还是item模板;因为所有这三个都是单独调用这同一个函数。对于产品和购物篮来说,我们都取得datacontrolrowtype.datarow行类型,因为这是我们的itemtemplate。

  因为我们给html页面中的所有控件都确定了唯一的id,所以我们能够使用行中的findcontrol函数。这将返回一个"object",如果该行中的任何控件有一个相匹配的id话。我们可以把它强制转换成我们期望的对象类型,例如一个"literal"或一个"htmlinputtext"域,然后经由它的textorvalue属性把数据指派给它。在每次绑定一个行时,它都被经由gridviewroweventargs.row属性传递给该函数。使用这种技术,我们就能够存取该行的dataitem,它包含来自于datasource的所有的行数据。然后,由我们来决定我们想从中提取哪些数据以及如何使用它。
在购物篮中,我们从dataitem中提取了名称,数量和价格三列数据,并且把它们指派给我们嵌入式在itemtemplate中的相关控件。对于datacontrolrowtype.footer,情况基本一致,除了我们从会话状态提取datasource的一个副本之外(getbasketdt();),因为我们想使用所有行中的信息生成总值及运送费用,而不仅仅是传递到该函数中的单行数据。

  六. 结论

  我希望通过本文,你已经掌握了使用gridview控件的基本知识及其它一些技巧。我们分析了实现gridview控件的一种方法以及如何控制其内容的生成。在下一篇中,我们将探讨gridview控件的数据来源,并与你共同建立实际的购物篮。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表