2004-10-6 + 学习PetShop3.0(7)SimplePager

SimplePager是继承自Repeater的一个自定义控件,在整个站中应用很广,下面通过Category.aspx这个页面具体的研究研究:)
先来看Category.aspx.cs,很奇怪吧,怎么没有和Load事件相关的方法呢?只有一个控制分页的PageChanged,而这个分页方法也有问题,每次都是获得缓存里的数据,然后改变的只CurrentPageIndex属性而已,并且该方法接受的参数竟然是DataGridPageChangedEventArgs,真晕,这个控件是一个Repeater嘛……
下面就让我们打开SimplePager.cs来看个究竟吧~~(两天的感冒刚好,目前精神百倍中……),其实看这个的时候最好是用.NET Reflector来查看,这样比较容易好辨认(我现在的电脑就把打开dll文件的默认程序设成了.NET Reflector)。
先来看第一个问题,在具体的页面中没有Load事件,那肯定是在控件的内部做了手脚

override protected void OnLoad(EventArgs e) {
if (Visible) {
string page = Context.Request[KEY_PAGE];
int index = (page != null) ? int.Parse(page) : 0;
SetPage(index);
}
}

当Load事件发生时就调用SetPage方法
public void SetPage(int index) {
//对DataGridPageChangedEventArgs有疑惑的可以看文章的最后
OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));
}

然后是OnPageIndexChanged
virtual protected void OnPageIndexChanged(DataGridPageChangedEventArgs e) {
if (PageIndexChanged != null)
PageIndexChanged(this, e);
}

PageIndexChanged是一个事件,使用了DataGridPageChangedEventHandler作为它的委托
public event DataGridPageChangedEventHandler PageIndexChanged;

这样就不难理解了,PageChanged就是在页面加载时的“Page_Load”方法,并且还是页数改变时相应的处理方法。换句话说,每次进入该页,程序都当成页数改变事件来处理。
从上面我们可以看到一个问题,即在这三个连续的方法中页数的传递都是通过
string page = Context.Request[KEY_PAGE];这里获得的值来进行的,好象CurrentPageIndex属性根本就没有用……
CurrentPageIndex的作用主要体现在分页方法这里
override protected void OnDataBinding(EventArgs e) {

//Work out which items we want to render to the page
int start = CurrentPageIndex * pageSize;
int size = Math.Min(pageSize, ItemCount - start);

IList page = new ArrayList();

//Add the relevant items from the datasource
for (int i = 0; i < size; i++)
page.Add(dataSource[start + i]);

//set the base objects datasource
base.DataSource = page;
base.OnDataBinding(e);

}

OnDataBinding是当服务器控件绑定到数据源时发生的DataBinding事件的处理方法。在这里有机会对数据源进行处理。而这里的确就是对数据源进行了处理,取到当前页的数据并把他们作为新的数据源赋给控件。
for (int i = 0; i < size; i++)
page.Add(dataSource[start + i]);

因为dataSource是实现了IList接口的数据,所以可以这样用索引器来操作数据,再往里面看,这些数据是什么呢?好象以前讨论过这个,数据源实际是一个ArrayList,里面放的是ProductInfo实体。
看到这里,或许你和我一样,会有这样的疑惑,既然在Load阶段就接收到了一个页数,为什么在这里还要另外的用一个,直接用一个不可以吗?我在这里的看法是,这样可以使程序的可读性更高,并且使控件的用户接口更加友好。
或者,那个变量根本就传不到OnDataBinding方法里面?这个我没有调试过,感兴趣的可以试试。
除了这里,Render方法也用CurrentPageIndex来实现上一页和下一页连接的显示。
顺便说一下ViewStatePager,这个是SimplePager的子类,主要的区别是该控件识别页数时使用了ViewState来完成,这样不至于和同一页面上的其他需要分页的控件(比如SimplePager)冲突。
最后说一个小发现
public DataGridPageChangedEventArgs(object commandSource, int newPageIndex)
{
this.commandSource = commandSource;
this.newPageIndex = newPageIndex;
}

这是通过.NET Reflector得到的DataGridPageChangedEventArgs的构造函数
public int NewPageIndex
{
get
{
return this.newPageIndex;
}
}
这是通过.NET Reflector得到的DataGridPageChangedEventArgs的NewPageIndex属性的定义。

你可能感兴趣的:(simple)