[Professional ASP.NET Design Pattern 读书笔记系列] 03 网络应用的分层以及重点的分离
1.一个简单的反Design Pattern的例子
数据库中有这样一张表,内容如下:
ProductId |
ProductName |
RRP |
SellingPrice |
1 |
Drill |
109.9900 |
99.9900 |
2 |
Hammer |
0.9900 |
7.9900 |
3 |
Shovel |
9.9900 |
9.9900 |
网页的目的是除了要显示商品名称,建议零售价RRP和销售价Selling Price之外,如果商品的销售价给比将以零售价低,还要显示销售价比零售价便宜了多少钱,以及显示便宜了的百分比。
同时,显示的表格上方还要有一个打折按钮,选项为不打折和打95折。打折之后的价格显示为SellingPrice,同时需要重新计算建议零售价RRP和95折的SellingPrice。
因此,为了显示数据库表中不存在的新的column,对拖拽到页面中的GridView改造如下:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1"
DataKeyNames="ProductId"
EmptyDataText="There are no data records to display."
OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="ProductId" HeaderText="ProductId"
ReadOnly="True" SortExpression="ProductId" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="RRP" HeaderText="RRP" SortExpression="RRP"
DataFormatString="{0:C}" />
<asp:TemplateField HeaderText="SellingPrice" SortExpression="SellingPrice">
<ItemTemplate>
<asp:Label ID="lblSellingPrice" runat="server" Text='<%# Bind("SellingPrice") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Discount">
<ItemTemplate>
<asp:Label runat="server" ID="lblDiscount"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Savings">
<ItemTemplate>
<asp:Label runat="server" ID="lblSavings"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
2. BoundField和TemplateField的作用是什么?
BoundField表明将表的这一行直接与数据库中对应的这一行的数据显示出来。如果直接使用BoundField将表和数据库绑定,那么后台程序将没有修改表中的内容的能力。为了使得后台能对表中的数据进行修改,必须要使得表格中的一格至少成为一个或者多个控件的容器,而TemplateField正好起到了这种容器的作用。
这里我们看到,在SellingPrice这一个column里面,Text='<%# Bind("SellingPrice")%>',这里这么书写的原因是,<TemplateField>标签并不具备直接绑定数据库的能力,因此在空间里必须使用Bind语句,将Label的内容与数据库的SellingPrice这个Field绑定起来。但是实际上这里并不需要,因为后台程序自动会为Label更换显示的文字。
3. OnRowDataBound如何理解?
OnRowDataBound是数据库表中的数据按Row与GridView每绑定完成一行就会触发的一个事件。后台代码为:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
decimal RRP = decimal.Parse(((System.Data.DataRowView)e.Row.DataItem)["RRP"].ToString());
decimal SellingPrice = decimal.Parse(((System.Data.DataRowView)e.Row.DataItem)["SellingPrice"].ToString());
Label lblSellingPrice = (Label)e.Row.FindControl("lblSellingPrice");
Label lblSavings = (Label)e.Row.FindControl("lblSavings");
Label lblDiscount = (Label)e.Row.FindControl("lblDiscount");
lblSavings.Text = DisplaySavings(RRP, ApplyExtraDiscountsTo(SellingPrice));
lblDiscount.Text = DisplayDiscount(RRP, ApplyExtraDiscountsTo(SellingPrice));
lblSellingPrice.Text = String.Format("{0:C}", ApplyExtraDiscountsTo(SellingPrice));
}
}
可以看到,在传入的参数 e 中,包含了该数据行的各个Field的值,只需要按名字取出,经过一定处理以后,就可以复制为Label显示。这样,就实现了对GridView的改造。