在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、概述 在web开发中,常常需要显示一些数据,而为了方便排版及浏览,我们只需要显示所有记录中的一部分。一般情况下,我们采用分页来实现这个需求。实现分页的方法多种多样,在本文中,我们采用了一个分页空间来记录记录总数、当前页、总页数及页面大小等。为了有一个直观上的印象,先展示该控件运行后的效果,效果如下图所示: 二、实现方案 为了实现该效果图,在asp.net中,可以使用Custom Controls and User Controls两种方式,User Controls的实现方式及其简单,而且使用起来和平时使用Controls的方式差别极大,所以我们采用Custom Controls实现。 参考资料:Professional ASP.NET 2.0 Server Control and Component Development 三、分页控件的实现 1)、新建一个ASP.NET Server Control项目, 2)、在该项目中添加一个ASP.NET Server Control的Item,并设置其Name为PageOn, 3)、修改该类继承于CompositeControl类,并修改其Attribute为如下所示: 复制代码 代码如下: [DefaultProperty("PageSize")] [ToolboxData("<{0}:PageOn runat=server Width=100%></{0}:PageOn>")] public class PageOn : CompositeControl 注:自定义控件必须继承自Control或者其子类。 4)、 定义需要被组合的控件 复制代码 代码如下: Label lblMessage; LinkButton btnFirst; LinkButton btnPrev; LinkButton btnNext; LinkButton btnLast; TextBox txtGoPage; Button btnGo; 5)、定义分页控件需要用到的Proptery 分页控件主要包括页面大小、当前页、总记录数及总页数等属性,并需要保存在ViewState中,详细代码如下所示: 复制代码 代码如下: public int RowCount { get { if (ViewState["m_rowCount"] == null || int.Parse(ViewState["m_rowCount"].ToString()) < 0) { ViewState["m_rowCount"] = 0; } return int.Parse(ViewState["m_rowCount"].ToString()); } set { if (value < 0) { ViewState["m_rowCount"] = 0; } else { ViewState["m_rowCount"] = value; } this.RecreateChildControls(); } } public int CurPage { get { if (ViewState["m_curPage"] ==null || int.Parse(ViewState["m_curPage"].ToString()) < 1) { ViewState["m_curPage"] = 1; } return int.Parse(ViewState["m_curPage"].ToString()); } set { if (value < 1) { ViewState["m_curPage"] = 1; } else if (value > PageCount) { ViewState["m_curPage"] = PageCount; } else { ViewState["m_curPage"] = value; } } } public int PageCount { get { return RowCount / PageSize + 1; } } public int PageSize { get { if (ViewState["m_pageSize"] ==null || int.Parse(ViewState["m_pageSize"].ToString()) < 1) { ViewState["m_pageSize"] = 15; } return int.Parse(ViewState["m_pageSize"].ToString()); } set { if (value > 0) { ViewState["m_pageSize"] = value; this.RecreateChildControls(); } } } 6)、生成自定义控件的子空间 生成自定义空间的子空间需要override基类Control中的CreateChildControls()方法,详细代码如下所示: 复制代码 代码如下: protected override void CreateChildControls() { Controls.Clear(); lblMessage = new Label(); lblMessage.Text = "当前第" + CurPage + "页 共" + PageCount + "页 共" + RowCount + "条记录"; lblMessage.ID = "lblMessage"; Controls.Add(lblMessage); btnFirst = new LinkButton(); btnFirst.Text = "首页"; btnFirst.CommandName = "first"; btnFirst.ID = "btnFirst"; if (CurPage <= 1) { btnFirst.Enabled = false; } Controls.Add(btnFirst); btnPrev = new LinkButton(); btnPrev.Text = "上一页"; btnPrev.CommandName = "prev"; btnPrev.ID = "btnPrev"; if (CurPage <= 1) { btnPrev.Enabled = false; } Controls.Add(btnPrev); btnNext = new LinkButton(); btnNext.Text = "下一页"; btnNext.CommandName = "next"; btnNext.ID = "btnNext"; if (CurPage >= PageCount) { btnNext.Enabled = false; } Controls.Add(btnNext); btnLast = new LinkButton(); btnLast.Text = "末页"; btnLast.CommandName = "last"; btnLast.ID = "btnLast"; if (CurPage >= PageCount) { btnLast.Enabled = false; } Controls.Add(btnLast); txtGoPage = new TextBox(); txtGoPage.TabIndex = 1; txtGoPage.ID = "txtGoPage"; txtGoPage.Attributes.Add("onkeyup", @"this.value=this.value.replace(/\D/g,'')"); txtGoPage.Attributes.Add("onafterpaste", @"this.value=this.value.replace(/\D/g,'')"); Controls.Add(txtGoPage); btnGo = new Button(); btnGo.TabIndex = 2; btnGo.CommandName = "go"; btnGo.Text = "GO"; btnGo.ID="btnGO"; Controls.Add(btnGo); Debug.WriteLine("ffffffffffffffffffffffffffffffffffffffffffffffffff"); base.CreateChildControls(); } 7)、定义自定义控件的布局 第6步完成后,所有定义的控件都会顺序显示到页面上了,但是这样的效果不友好,如果对于多行的空间更是如此,所有我们需要定义控件的布局,自定义控件的布局需要重写RenderContents()方法及TagKey属性,此示例中的代码如下所示: 复制代码 代码如下: protected override void RenderContents(HtmlTextWriter output) { output.RenderBeginTag(HtmlTextWriterTag.Tr); output.AddStyleAttribute("text-align", "left"); output.RenderBeginTag(HtmlTextWriterTag.Td); output.Write(" "); lblMessage.RenderControl(output); output.RenderEndTag(); output.AddStyleAttribute("text-align", "right"); output.RenderBeginTag(HtmlTextWriterTag.Td); btnFirst.RenderControl(output); output.Write(" "); btnPrev.RenderControl(output); output.Write(" "); btnNext.RenderControl(output); output.Write(" "); btnLast.RenderControl(output); output.Write("到"); output.AddStyleAttribute(HtmlTextWriterStyle.Width, "30px"); txtGoPage.RenderControl(output); output.Write("页"); btnGo.RenderControl(output); output.Write(" "); output.RenderEndTag(); output.RenderEndTag(); } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Table; } } 上面的代码中,我们使用Table来布局,也可以使用其它的布局方式,比如DIV+CSS。 8)、捕捉并处理控件的事件 到此以后,这些代码已经可以生成文章开头图所显示的效果,但是什么事情也做不了,不能响应该控件上的事件,所有还需要继续实现该控件上的事件代码,实现这些事件采用冒泡所有子控件的事件来实现。 首先,定义一个委托: 复制代码 代码如下: public delegate void PageOnEventHandler(object sender, EventArgs args); 其次,定义基于该委托的事件: 复制代码 代码如下: public event PageOnEventHandler RecPageChanged; 最后,重写冒泡事件,并根据参数特征,捕获需要处理的事件,使其调用需要的方法。 复制代码 代码如下: protected override bool OnBubbleEvent(object source, EventArgs args) { bool handled = false; CommandEventArgs cea = args as CommandEventArgs; if(cea == null) { return handled; } switch (cea.CommandName) { case "first": handled = true; CurPage = 1; break; case "prev": handled = true; if (CurPage > 1) { CurPage--; } else { CurPage = 1; } break; case "next": handled = true; if (CurPage < PageCount) { CurPage ++ ; } else { CurPage = PageCount; } break; case "last": handled = true; CurPage = PageCount; break; case "go": string strGo = txtGoPage.Text.Trim(); int iGo; if (!string.IsNullOrEmpty(strGo) && int.TryParse(strGo, out iGo)) { handled = true; CurPage = iGo; } break; } if (handled) { if (this.RecPageChanged != null) { RecPageChanged(this, args); this.RecreateChildControls(); } return handled; } else { return base.OnBubbleEvent(source, args); } } 到此就完成了分页控件的开发。 注:可以定制该控件的样式,或者使用属性暴露子控件的属性来控制样式等. 四、使用分页控件 完成自定义控件的开发后,在Toolbox中Choose Items或者直接在需要使用该自定义控件的项目中引用该项目或者DLL,即可在Toolbox中显示自定义控件了。然后用拖拽的方式即可把分页控件放到需要的地方,就像使用button控件一样简单。 然后再该页面的后台代码的OnLoad事件中,注册需要被调用的方法到该控件的RecPageChanged事件中,如下所示: 复制代码 代码如下: PageOn1.RecPageChanged += new CustomControl.PageOnEventHandler(PageOn1_RecPageChanged); 最后,只需要在方法PageOn1_RecPageChanged中编写自己的代码即可。 复制代码 代码如下: void PageOn1_RecPageChanged(object sender, EventArgs args) { //To do something } 控件的详细代码如下: 复制代码 代码如下: namespace CustomControl { public delegate void PageOnEventHandler(object sender, EventArgs args); [DefaultProperty("PageSize")] [ToolboxData("<{0}:PageOn runat=server Width=100%></{0}:PageOn>")] public class PageOn :CompositeControl { #region Label lblMessage; LinkButton btnFirst; LinkButton btnPrev; LinkButton btnNext; LinkButton btnLast; TextBox txtGoPage; Button btnGo; #endregion protected override void CreateChildControls() { Controls.Clear(); lblMessage = new Label(); lblMessage.Text = "当前第" + CurPage + "页 共" + PageCount + "页 共" + RowCount + "条记录"; lblMessage.ID = "lblMessage"; Controls.Add(lblMessage); btnFirst = new LinkButton(); btnFirst.Text = "首页"; btnFirst.CommandName = "first"; btnFirst.ID = "btnFirst"; if (CurPage <= 1) { btnFirst.Enabled = false; } Controls.Add(btnFirst); btnPrev = new LinkButton(); btnPrev.Text = "上一页"; btnPrev.CommandName = "prev"; btnPrev.ID = "btnPrev"; if (CurPage <= 1) { btnPrev.Enabled = false; } Controls.Add(btnPrev); btnNext = new LinkButton(); btnNext.Text = "下一页"; btnNext.CommandName = "next"; btnNext.ID = "btnNext"; if (CurPage >= PageCount) { btnNext.Enabled = false; } Controls.Add(btnNext); btnLast = new LinkButton(); btnLast.Text = "末页"; btnLast.CommandName = "last"; btnLast.ID = "btnLast"; if (CurPage >= PageCount) { btnLast.Enabled = false; } Controls.Add(btnLast); txtGoPage = new TextBox(); txtGoPage.TabIndex = 1; txtGoPage.ID = "txtGoPage"; txtGoPage.Attributes.Add("onkeyup", @"this.value=this.value.replace(/\D/g,'')"); txtGoPage.Attributes.Add("onafterpaste", @"this.value=this.value.replace(/\D/g,'')"); Controls.Add(txtGoPage); btnGo = new Button(); btnGo.TabIndex = 2; btnGo.CommandName = "go"; btnGo.Text = "GO"; btnGo.ID="btnGO"; Controls.Add(btnGo); Debug.WriteLine("ffffffffffffffffffffffffffffffffffffffffffffffffff"); base.CreateChildControls(); } public int RowCount { get { if (ViewState["m_rowCount"] == null || int.Parse(ViewState["m_rowCount"].ToString()) < 0) { ViewState["m_rowCount"] = 0; } return int.Parse(ViewState["m_rowCount"].ToString()); } set { if (value < 0) { ViewState["m_rowCount"] = 0; } else { ViewState["m_rowCount"] = value; } this.RecreateChildControls(); } } public int CurPage { get { if (ViewState["m_curPage"] ==null || int.Parse(ViewState["m_curPage"].ToString()) < 1) { ViewState["m_curPage"] = 1; } return int.Parse(ViewState["m_curPage"].ToString()); } set { if (value < 1) { ViewState["m_curPage"] = 1; } else if (value > PageCount) { ViewState["m_curPage"] = PageCount; } else { ViewState["m_curPage"] = value; } } } public int PageCount { get { return RowCount / PageSize + 1; } } public int PageSize { get { if (ViewState["m_pageSize"] ==null || int.Parse(ViewState["m_pageSize"].ToString()) < 1) { ViewState["m_pageSize"] = 15; } return int.Parse(ViewState["m_pageSize"].ToString()); } set { if (value > 0) { ViewState["m_pageSize"] = value; this.RecreateChildControls(); } } } protected override void RenderContents(HtmlTextWriter output) { output.RenderBeginTag(HtmlTextWriterTag.Tr); output.AddStyleAttribute("text-align", "left"); output.RenderBeginTag(HtmlTextWriterTag.Td); output.Write(" "); lblMessage.RenderControl(output); output.RenderEndTag(); output.AddStyleAttribute("text-align", "right"); output.RenderBeginTag(HtmlTextWriterTag.Td); btnFirst.RenderControl(output); output.Write(" "); btnPrev.RenderControl(output); output.Write(" "); btnNext.RenderControl(output); output.Write(" "); btnLast.RenderControl(output); output.Write("到"); output.AddStyleAttribute(HtmlTextWriterStyle.Width, "30px"); txtGoPage.RenderControl(output); output.Write("页"); btnGo.RenderControl(output); output.Write(" "); output.RenderEndTag(); output.RenderEndTag(); } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Table; } } public event PageOnEventHandler RecPageChanged; protected override bool OnBubbleEvent(object source, EventArgs args) { bool handled = false; CommandEventArgs cea = args as CommandEventArgs; if(cea == null) { return handled; } switch (cea.CommandName) { case "first": handled = true; CurPage = 1; break; case "prev": handled = true; if (CurPage > 1) { CurPage--; } else { CurPage = 1; } break; case "next": handled = true; if (CurPage < PageCount) { CurPage ++ ; } else { CurPage = PageCount; } break; case "last": handled = true; CurPage = PageCount; break; case "go": string strGo = txtGoPage.Text.Trim(); int iGo; if (!string.IsNullOrEmpty(strGo) && int.TryParse(strGo, out iGo)) { handled = true; CurPage = iGo; } break; } if (handled) { if (this.RecPageChanged != null) { RecPageChanged(this, args); this.RecreateChildControls(); } return handled; } else { return base.OnBubbleEvent(source, args); } } } } OK,完成 |
请发表评论