首页点击内容详细页时,跳转到了products.aspx这个页面,接下来就来分析一下这个页面了.
products.aspx页面代码很简单,只有几行
<%@ Page AutoEventWireup="true" Language="C#" MasterPageFile="~/MasterPage.master" Title="Products" Inherits="PetShop.Web.Products" CodeFile="~/Products.aspx.cs" %>
<%@ Register Src="Controls/ProductsControl.ascx" TagName="ProductsControl" TagPrefix="PetShopControl" %>
<asp:Content ID="cntPage" ContentPlaceHolderID="cphPage" runat="Server" EnableViewState="false">
<PetShopControl:ProductsControl ID="ProductsControl1" runat="server" />
</asp:Content>
由于NET2.0全面使用了母版页,所以基本的不必常改动的地方都放在这了。这也就简化了代码。而且开发的效率更高了。看了页面代码,加截了用户控件Controls/ProductsControl.ascx然后其他什么东西都没,那这样的话,直接分析这一用户控件的功能也就行了。打开ProductsControl.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ProductsControl.ascx.cs" Inherits="PetShop.Web.ProductsControl" EnableViewState="false" %>
<%@ Register TagPrefix="PetShopControl" Namespace="PetShop.Web" %>
使用Register为注册用户控件这跟建立一个自定义用户控件又有点不同,因为少了个Scr,也就是用户控件的出处,使用了名称空间为PetShop.Web
<%@ OutputCache Duration="100000" VaryByParam="page;categoryId" %>
使用了页面缓存技术,之前看了一篇分析说PetShop4使用了2种缓存机制,一种是应该程序缓存,一种是页输出缓存,OutputCache 设置了页级的缓存,时间为Duration为1000000秒,对page,categoryID控件建立缓存
先研究一下后台代码
- protected void Page_Load(object sender, EventArgs e) {
- this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
- }
cachedependency 2.0里的缓存机制 迟点再再学习一下缓存机制
还有一行是PageChanged()
/// <summary>
/// Rebind control
/// </summary>
protected void PageChanged(object sender, DataGridPageChangedEventArgs e) {
//reset index
productsList.CurrentPageIndex = e.NewPageIndex;
//get category id
string categoryKey = Request.QueryString["categoryId"];
//bind data
Product product = new Product();
productsList.DataSource = product.GetProductsByCategory(categoryKey);
productsList.DataBind();
}
这一段从写法的结构上看像是在写切换页时数据的绑定.这里是实例化一个product然后再由他的GetProductsByCategory方法进行读取数据,追踪一下Product类看看
namespace PetShop.BLL {
public class Product {
private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();
public IList<ProductInfo> GetProductsByCategory(string category) {
if(string.IsNullOrEmpty(category))
return new List<ProductInfo>();
return dal.GetProductsByCategory(category);
}
public IList<ProductInfo> GetProductsBySearch(string text) {
if (string.IsNullOrEmpty(text.Trim()))
return new List<ProductInfo>();
string[] keywords = text.Split();
return dal.GetProductsBySearch(keywords);
}
public ProductInfo GetProduct(string productId) {
if(string.IsNullOrEmpty(productId))
return new ProductInfo();
return dal.GetProduct(productId);
}
}
}
来到了三层结果中的业务逻辑层了.再来研究一下这个类的作用
三个方法GetProductsByCategory(string category),根据类别返回一个IList<ProductInfo>的东西
用了IList<>,这个IList就是IndexedList,意思是说可以根据索引访问的列表。那个尖角括号是说,这里用了泛型
dal.GetProductsByCategory(category)这样就读到了数据?下一章再分析这个怎么来读取数据的。这里不讨论
第二个方法使用的是
GetProductsBySearch这个产品根据搜索关键字返回一下IList<>类型的方法
第三个是public ProductInfo GetProduct(string productId) 根据产品的ID返回一个ProductInfo这个是个实体类。
好了,不再深入解读。
返回来ProductsControl.ascx 要不越读越离得远了,按照三层的思想慢慢再看。
productsList.DataSource = product.GetProductsByCategory(categoryKey);
productsList.DataBind();
productsList的数据源来自己实例化的product所读取categoryKey这个分类所在的全部数据,页DataSource绑定是的一个IList<>类型。怎么productsList.DataSource可以绑定这种类型吗?等一下再分析。
然后进行绑定。这样产品的页面就可以显示了。
但看回HTML的页面里,有些和其他地方不同的东西
<PetShopControl:CustomList ID="productsList" runat="server" EmptyText="No products found." OnPageIndexChanged="PageChanged" PageSize="4" RepeatColumns="2" CellPadding="16" CellSpacing="0" Width="500px">
<ItemTemplate>
<table cellpadding="0" cellspacing="0">
<tr>
<td valign="top" width="91"><a href='Items.aspx?productId=<%# Eval("Id") %>&categoryId=<%# Eval("categoryId") %>'><img id="imgProduct" alt='<%# Eval("Name") %>' src='<%# Eval("Image") %>' style="border-width: 0px;" runat="server" /></a></td>
<td width="26"> </td>
<td valign="top" width="120"><a href='Items.aspx?productId=<%# Eval("Id") %>&categoryId=<%# Eval("categoryId") %>'><div class="productName"><%# Eval("Name") %></div></a><div class="productDescription"><%# Eval("Description") %></div></td>
</tr>
</table>
</ItemTemplate>
<ItemStyle HorizontalAlign="Left" VerticalAlign="Top" />
</PetShopControl:CustomList>
PetShopControl:CustomList 这个是什么东西,像是自定义的控件,CustomList是个自己写的东西,并不是控件里自带的。
存在于app_code目录,文件名:CustomList.cs
public class CustomList : DataList {
//Static constants
protected const string HTML1 = "<table cellpadding=0 cellspacing=0><tr><td colspan=2>";
protected const string HTML2 = "</td></tr><tr><td class=paging align=left>";
protected const string HTML3 = "</td><td align=right class=paging>";
....
原来是继承了DataList对象,这样,CustomList就有了DataList的功能了。
override public object DataSource {
set {
//This try catch block is to avoid issues with the VS.NET designer
//The designer will try and bind a datasource which does not derive from ILIST
try {
dataSource = (IList)value;
ItemCount = dataSource.Count;
}
catch {
dataSource = null;
ItemCount = 0;
}
}
}
这里重写了DataSource,数据源的绑定是一个IList类型以及读取数据后的显示问题。这样Products.aspx这页面也就差不多分析完了