Samuel Learning

  • 联系
  •  
  • 管理

文章分类(203)

  • 01 ASP/HTML(6)
  • 02 Script/CSS(16)
  • 03 C/C++
  • 04 XML(4)
  • 05 微软编程(26)
  • 06 J2EE(60)
  • 09 Linux(14)
  • 10 Database(27)
  • 11 报表打印
  • 12 打包安装(1)
  • 13 模式重构(2)
  • 14 系统架构
  • 15 敏捷开发(11)
  • 16 案例分析(30)
  • 17 Workflow(1)
  • 18 配置管理(1)
  • 19 项目管理
  • 20 英语(4)

新闻分类(52)

  • CXF学习
  • Hibernate学习(1)
  • iBatis学习(16)
  • Struts1学习(1)
  • Struts2学习(34)

.NET资源

  • adxmenu
  • C# Open Source
  • DNN Directory
  • M2Land
  • Windows Form FAQ
  • 中国DNN
  • 中国DNN联盟

Ajax

  • DoJo
  • GWT
  • JQuery
  • jquery autocomplete
  • jquery flexgrid
  • JQuery Form
  • jquery masked input
  • JQuery UI
  • jquery validation
  • Jquery 图表
  • jquery报表
  • jquery插件集合
  • Qooxdoo
  • Tibco GI
  • YUI
  • YUI-EXT
  • ZeroKode

Java开源

  • ABLE
  • Agile Tao
  • Ajax4JSF
  • Alfresco
  • AppFuse
  • Compiere
  • Equinox
  • Findbugs
  • Geronimo
  • Grails
  • Harmony
  • Hibernate论坛
  • JAG
  • Java开源大全
  • Java视线论坛
  • jBPM工作流
  • JSFTutorials
  • Nereide ERP
  • Ofbiz ERP
  • Opentaps ERP
  • operamasks
  • Petstore
  • Prototype.js
  • RIFE
  • Runa
  • SpringSide
  • Struts Menu
  • Sun Glassfish
  • Trails
  • YUI4JSF
  • 满江红

Mobile

  • Sencha

WEB资源

  • DHTML中心
  • DHTML参考手册
  • DHTML文档
  • EclipsePlugin
  • Firebug
  • GRO Clinux
  • jMaki
  • JSTL文档
  • LoadIcon
  • Openlaszlo
  • Struts Menu 展示
  • Web Test Tools
  • WebCtrs
  • Webdeveloper
  • 中国RIA开发者论坛

Workflow

  • E-Workflow
  • JBPM
  • OpenWFE
  • OSWorkflow
  • WFMC
  • Workflow Research

其他连接

  • confach
  • CPP
  • ejay
  • Giovanni
  • 丹佛
  • 交大e-learning
  • 交大研究生院
  • 可恶的猫
  • 天天@blog
  • 我的相册
  • 阿飞

大牛人

  • 32篇JBPM
  • David.Turing
  • HongSoft@业务集成
  • Joel
  • Koen Aers
  • Martinfowler
  • Raible Matt
  • Raible Wiki
  • Scott W.Ambler
  • Tom Baeyens
  • Uncle Bob
  • 一个世界在等待
  • 子在川上曰
  • 小布老师
  • 小明
  • 差沙
  • 徐昊
  • 江南白衣
  • 汪博士
  • 汪小金
  • 银狐999

开源软件

  • 2Bizbox ERP
  • CompiereCRM&ERP
  • EGW
  • Vtiger CRM
  • webERP

敏捷

  • Canoo
  • Cruisecontrol
  • DBUnit
  • EL4Ant
  • Extreme Programming
  • Fit
  • Fitnesse
  • JFrog
  • Liquibase
  • Maven
  • MockObjects
  • Selenium
  • Squish
  • xpairtise
  • XPlanner
  • XProgramming
  • 敏捷联盟

数据库

  • Oracle 中国
  • Oracle-ERP
  • Oracle在线社区

未归类

  • Aquarius Orm Studio
  • mambo建站系统
  • Oracle产品下载
  • 远程同步管理工具Capivara

经典框架

  • Apache Shale
  • formdef-struts
  • FreeMarker 主页
  • JBoss Seam
  • JSF 中心
  • JSF 入门应用
  • JSF中国
  • MyFaces官方
  • Spring 社区
  • Spring专业网站
  • Spring中文论坛
  • Spring参考手册
  • Spring官方网站
  • strecks-struts
  • Struts1
  • Struts2
  • Struts-layout
  • StrutsWiKi
  • Tapestry WIKI
  • Tapestry 官方
  • Tapestry4开发指南
  • Tapestry中文文档
  • Webwork2文档
  • Wicket

网络教程

  • Laliluna
  • RoseIndia
  • Sang Shin
  • Visualbuilder

著名站点

  • Buildix
  • Dev2Dev
  • IBM dev中国
  • InfoQ
  • ITPub
  • Java Eye
  • Java Research
  • JavaRead
  • JavaWorldTW
  • Matrix
  • PHP100
  • PHPX
  • SpringSideWiKi
  • TheServerSide
  • TWPHP
  • 中国工作流论坛

项目管理

  • 管理人网

最新评论

View Post

Part 5 PetShop3.0场景幕后实现(下)

以上按12个场景进行代码分析,下面从技术点的角度来分析代码:

技术点1:这个应用中,在表示层大量使用了一种自定义控件,继承了Repeater类。先看看全文检索宠物调用Simplepager的方式:

Part 1 页面代码,先引入标签,后使用标签。使用标签时,先设置属性,后设置模板。这个标签可以设置页面大小,当没有条目时,给出提示,分页时用了一个onpageindexchanged事件。

<PetsControl:simplepager id="products" runat="server" pagesize="4" emptytext="No products found." onpageindexchanged="PageChanged">
                    
<headertemplate>
                        
<table cellpadding="0" cellspacing="0">
                            
<tr class="gridHead">
                                
<td>Product ID</td>
                                
<td>Name</td>
                                
<td>Description</td>
                            
</tr>
                    
</headertemplate>
                    
<itemtemplate>
                        
<tr class="gridItem">
                            
<td><%# DataBinder.Eval(Container.DataItem, "Id") %></td>
                            
<td><a href='Items.aspx?productId=<%# DataBinder.Eval(Container.DataItem, "Id") %>'><%# DataBinder.Eval(Container.DataItem, "Name") %></a></td>
                            
<td><%# DataBinder.Eval(Container.DataItem, "Description") %></td>
                        
</tr>
                    
</itemtemplate>
                    
<footertemplate>
                        
</tbody>
                    
</table>
                
</footertemplate>
                
</PetsControl:simplepager>

在onpageindexchanged事件中,绑定数据源。

protected void PageChanged(object sender, DataGridPageChangedEventArgs e) {
            products.CurrentPageIndex 
= e.NewPageIndex;

            
// Get the search terms from the query string
            string searchKey = WebComponents.CleanString.InputText(Request["keywords"], 100);

            
if (searchKey != ""){

                
// Create a data cache key
                string cacheKey = "search" + searchKey;

                
// Check if the objects are in the cache
                if(Cache[cacheKey] != null){
                    products.DataSource 
= (IList)Cache[cacheKey];
                }
else{
                    
// If that data is not in the cache then use the business logic tier to fetch the data
                    Product product = new Product();
                    IList productsBySearch 
= product.GetProductsBySearch(searchKey);
                    
// Store the results in a cache
                    Cache.Add(cacheKey, productsBySearch, null, DateTime.Now.AddHours(12), Cache.NoSlidingExpiration , CacheItemPriority.High, null);
                    products.DataSource 
= productsBySearch;
                }


                
// Databind the data to the controls
                products.DataBind();
            }

        }

 

Part 2 看看SimplePager的源代码。在源代码中,SimplePager继承了Repeater,主要增添了分页功能,大部分是属性的定义,增加了OnPageIndexChanged事件,重写了OnLoad、Render和OnDataBinding方法。Onload获取请求参数,激发分页事件。Render描述了如何渲染这个控件,OnDataBinding告诉控件要绑定哪些数据。

public class SimplePager : Repeater {

        
//Static constants
        protected const string HTML1 = "<table cellpadding=0 cellspacing=0><tr><td colspan=2>";
        
protected const string HTML2 = "</td></tr><tr class=gridNav><td>";
        
protected const string HTML3 = "</td><td align=right>";
        
protected const string HTML4 = "</td></tr></table>";
        
private static readonly Regex RX = new Regex(@"^&page=\d+", RegexOptions.Compiled);
        
private const string LINK_PREV = "<a href=?page={0}><img src=Images/buttonPrev.gif alt=Previous border=\"0\"></a>";
        
private const string LINK_MORE = "<a href=?page={0}><img src=Images/buttonMore.gif alt=More border=\"0\"></a>";
        
private const string KEY_PAGE = "page";
        
private const string COMMA = "?";
        
private const string AMP = "&";

        
protected string emptyText;
        
private IList dataSource;
        
private int pageSize = 10;
        
private int currentPageIndex;
        
private int itemCount;
        
        
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;
                }

            }

        }


        
public int PageSize {
            
get { return pageSize; }
            
set { pageSize = value; }
        }


        
protected int PageCount {
            
get { return (ItemCount - 1) / pageSize; }
        }


        
virtual protected int ItemCount {
            
get { return itemCount; }
            
set { itemCount = value; }
        }


        
virtual public int CurrentPageIndex {
            
get { return currentPageIndex; }
            
set { currentPageIndex = value; }
        }


        
public string EmptyText {
            
set { emptyText = value; }
        }


        
public void SetPage(int index) {
            OnPageIndexChanged(
new DataGridPageChangedEventArgs(null, index));
        }


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

        }



        
/**//// <summary>
        
/// Overriden method to control how the page is rendered
        
/// </summary>
        
/// <param name="writer"></param>

        override protected void Render(HtmlTextWriter writer) {
            
            
//Check there is some data attached
            if (ItemCount == 0) {
                writer.Write(emptyText);
                
return;
            }


            
//Mask the query
            string query = Context.Request.Url.Query.Replace(COMMA, AMP);
            query 
= RX.Replace(query, string.Empty);

            
// Write out the first part of the control, the table header
            writer.Write(HTML1);
            
            
// Call the inherited method
            base.Render(writer);

            
// Write out a table row closure
            writer.Write(HTML2);
            
            
//Determin whether next and previous buttons are required
            
//Previous button?
            if (currentPageIndex > 0)
                writer.Write(
string.Format(LINK_PREV, (currentPageIndex - 1) + query));

            
//Close the table data tag
            writer.Write(HTML3);

            
//Next button?
            if (currentPageIndex < PageCount)
                writer.Write(
string.Format(LINK_MORE, (currentPageIndex + 1) + query));

            
//Close the table
            writer.Write(HTML4);
        }


        
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);
            
        }


        
public event DataGridPageChangedEventHandler PageIndexChanged;

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

    }

Part 3 从上面的代码你可以看出SimplePager有一个致命的缺点就是:如果一个页面内有两个SimplePager控件怎么办?如果他们还依赖于请求的URL附带参数的话,两个控件岂不是会冲突?ViewStatePager正是为解决这个问题的,在ViewStatePager中用ViewState记住各自控件的记录数和当前页数。调用这个控件的地方是购物车页面。

public class ViewStatePager : SimplePager {

        
private const string KEY_ITEM_COUNT = "ItemCount";
        
private const string KEY_CURRENT_PAGE_INDEX = "CurrentPageIndex";
        
private const string IMG_PREV = "Images/buttonPrev.gif";
        
private const string IMG_MORE = "Images/buttonMore.gif";
        
private const string ALT_PREV = "Previous";
        
private const string ALT_MORE = "More";
        
        
private ImageButton btnPrev;
        
private ImageButton btnMore;

        
override protected int ItemCount {
            
get { return (int)ViewState[KEY_ITEM_COUNT]; }
            
set { ViewState[KEY_ITEM_COUNT] = value; }
        }


        
override public int CurrentPageIndex {
            
get { return (int)ViewState[KEY_CURRENT_PAGE_INDEX]; }
            
set { ViewState[KEY_CURRENT_PAGE_INDEX] = value; }
        }


        
override protected void OnLoad(EventArgs e) {
            
if (!Page.IsPostBack && Visible) {
                CurrentPageIndex 
= 0;
                SetPage(
0);
            }

        }


        
private void PreviousClicked(object sender, ImageClickEventArgs e) {
            OnPageIndexChanged(
new DataGridPageChangedEventArgs(sender, CurrentPageIndex - 1));
        }


        
private void MoreClicked(object sender, ImageClickEventArgs e) {
            OnPageIndexChanged(
new DataGridPageChangedEventArgs(sender, CurrentPageIndex + 1));
        }


        
override protected void CreateControlHierarchy(bool useDataSource) {
            
base.CreateControlHierarchy(useDataSource);

            btnPrev 
= new ImageButton();
            btnPrev.ImageUrl 
= IMG_PREV;
            btnPrev.AlternateText 
= ALT_PREV;
            btnPrev.Click 
+= new ImageClickEventHandler(PreviousClicked);
            Controls.Add(btnPrev);
            
            btnMore 
= new ImageButton();
            btnMore.ImageUrl 
= IMG_MORE;
            btnMore.AlternateText 
= ALT_MORE;
            btnMore.Click 
+= new ImageClickEventHandler(MoreClicked);
            Controls.Add(btnMore);
        }


        
override protected void OnPreRender(EventArgs e) {
            btnPrev.Visible 
= CurrentPageIndex > 0;
            btnMore.Visible 
= CurrentPageIndex < PageCount;
        }


        
override protected void Render(HtmlTextWriter writer) {
            
if (ItemCount == 0) {
                writer.Write(emptyText);
                
return;
            }


            writer.Write(HTML1);

            
for (int i = 0, j = Controls.Count - 2; i < j; i++)
                Controls[i].RenderControl(writer);
            
            writer.Write(HTML2);
            btnPrev.RenderControl(writer);
            writer.Write(HTML3);
            btnMore.RenderControl(writer);
            writer.Write(HTML4);
        }

    }

未完待续

posted on 2006-01-23 09:05 MingIsMe 阅读(548) 评论(0)  编辑  收藏 所属分类: 16 案例分析

 
Powered by:
BlogJava
Copyright © MingIsMe