相信大多数程序员最开始都想写一些自定义的控件,而我们最常用的到就是分页控件,所以我希望在这里将自己的一点心得与大家分享,讲讲分页控件的原理。
起始自定义控件最终仍然是一个类,即是object,那我们如果使用它呢,因为微软框架的自定义空间接口是System.Web.UI.WebControls.WebControl,所有的自定义控件都要继承与这个类,所以我们先声明一个类Page01,让这个类继承System.Web.UI.WebControls.WebControl,而由于分页控件需要在点击翻页的按钮时触发数据的回传,所以还必须实现接口IPostBackEventHandler,所以我们新建一个类,代码如下:
[DefaultProperty(""),ToolboxData("<{0}:Page01 runat=/"server/"></{0}:Page01>")]
public class Page01 : System.Web.UI.WebControls.WebControl,IPostBackEventHandler
{
..... 这里我们呆会要写类具体的属性,字段和方法
}
其中最桑面一行[DefaultProperty(""),ToolboxData("<{0}:Page01 runat=/"server/"></{0}:Page01>")]为自定义属性,这里指明了我们在前台调用时的语法格式。
一个分页控件不要的属性,每页显示的记录数,总记录数,当前页数,总页数,这里我再加上控件占用的宽度
private int record_Count;//总记录数
private int page_Count;//总页数
private int page_Size = 2;//每页显示记录数
private int page_Current = 1;//当前页数
private int page_width = 700;//宽度
private string page_Index = "";
[Bindable(true), Category("Appearance"), DefaultValue("")]
最后一句用于制定该空间可以用于绑定等信息。为微软底层提供的框架。
申明完字段,我们声明属性为字段赋值和读取指
public int Page_Width
{
get { return page_width; }
set { page_width = value; }
}
public int Record_Count
{
get { return record_Count; }
set { record_Count = value; }
}
public int Page_Count
{
get { return page_Count; }
set { page_Count = value; }
}
public int Page_Size
{
get { return page_Size; }
set { page_Size = value; }
}
public int Page_Current
{
get { return page_Current; }
set { page_Current = value; }
}
public string Page_Index
{
get { return page_Index; }
set { page_Index = value; }
}
由于自定义控件继承与webcontrols,所以我们可以重载Render方法重新绘制页面的输出,这个Render有个类型为HtmlTextWriter的参数,调用该实例的Write方法就可像页面输出指定字符串。
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<div class=/"/">/n");
writer.Write("记录数:");
writer.Write(record_Count);
writer.Write(" 总页数:");
writer.Write(page_Count + " ");
if (page_Current != 1)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, (page_Current - 1).ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '上一页' />");
}
for (int i = 1; i <= page_Count; i++)
{
if (i == page_Current)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, i.ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '" + i + "' />");
}
else
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, i.ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '" + i + "' />");
}
}
if (page_Current != page_Count)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, (page_Current + 1).ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '下一页' />");
}
writer.Write("</div>/n");
}
其中的逻辑思路笔者可自定义,如当为第一页时不显示上一页,或让第一页的按钮为不可点击状态等等。
我们还要定义一个委托和事件,让某些具体的事件发生时触发,这里就是翻页事件
/// <summary>
/// 定义委托,实现翻页时触发 事件
/// </summary>
/// <param name="sender">发送通知的对象</param>
/// <param name="args">包含所有接受者需要的附件信息</param>
public delegate void ItemPageIndexChanged(object sender, PageEventArgs args);
/// <summary>
/// 定义执行的事件
/// </summary>
public event ItemPageIndexChanged PageChangeIndex;
最后我们就要调用继承于IPostBackEventHandler这个类的方法RaisePostBackEvent来处理数据回传时我们要做的操作
public void RaisePostBackEvent(string eventArgument)
{
try
{
this.Page_Current = Int32.Parse(eventArgument);
}
catch
{
this.page_Current = 1;
}
PageEventArgs e = new PageEventArgs();
e.NewPageIndex = page_Current;
PageChangeIndex(this, e);
}
此时这个eventArgument参数就是我们回传的页数。方法里我们将当前页重新赋值,并声明要改变状态的PageEventArgs 对象实例,将它的NewPageIndex设置为当前页数,PageEventArgs类声明如下
public class PageEventArgs : EventArgs
{
/// <summary>
/// 最新页面
/// </summary>
private int newpageindex;
/// <summary>
/// 属性设置最新页面的页码值
/// </summary>
public int NewPageIndex
{
get { return newpageindex; }
set { newpageindex = value; }
}
}
即是我们在触发时间时要传递的对象。
这样我们就定义完了一个自定义控件,那我们在使用的时候需按照如下格式,在需要用到控件的前台页面最上面声明格式,在需要放置控件的地方调用<%@ Register Assembly="DBUtility" Namespace="DBUtility" TagPrefix="cc2" %>
其中Assembly为程序集名称,Namespace为命名空间名称,TagPrefix为用户自己定义的控件前缀,在调用处
<cc2:Page01 ID="Page1" runat="server" Page_Count="10" />即完成了控件的调用,那后台实现翻页事件,
this.Page1.PageChangeIndex += new Page01.ItemPageIndexChanged(Page1_PageChangeIndex);
void Page1_PageChangeIndex(object sender, DBUtility.PageEventArgs args)
{
this.Page1.Page_Current = args.NewPageIndex;
SetValue();
}
这里的SetValue()就是翻页完成后用户根据需要定义的方法。
那完整的代码如下:
文件Page01.cs类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Web.UI;
using System.Web;
using System.Web.UI.WebControls;
namespace DBUtility
{
[DefaultProperty(""),ToolboxData("<{0}:Page01 runat=/"server/"></{0}:Page01>")]
public class Page01 : System.Web.UI.WebControls.WebControl,IPostBackEventHandler
{
private int record_Count;//总记录数
private int page_Count;//总页数
private int page_Size = 2;//每页显示记录数
private int page_Current = 1;//当前页数
private int page_width = 700;//宽度
private string page_Index = "";
[Bindable(true), Category("Appearance"), DefaultValue("")]
public int Page_Width
{
get { return page_width; }
set { page_width = value; }
}
public int Record_Count
{
get { return record_Count; }
set { record_Count = value; }
}
public int Page_Count
{
get { return page_Count; }
set { page_Count = value; }
}
public int Page_Size
{
get { return page_Size; }
set { page_Size = value; }
}
public int Page_Current
{
get { return page_Current; }
set { page_Current = value; }
}
public string Page_Index
{
get { return page_Index; }
set { page_Index = value; }
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<div class=/"/">/n");
writer.Write("记录数:");
writer.Write(record_Count);
writer.Write(" 总页数:");
writer.Write(page_Count + " ");
if (page_Current != 1)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, (page_Current - 1).ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '上一页' />");
}
for (int i = 1; i <= page_Count; i++)
{
if (i == page_Current)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, i.ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '" + i + "' />");
}
else
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, i.ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '" + i + "' />");
}
}
if (page_Current != page_Count)
{
writer.Write("<INPUT οnclick=/"javascript:" + Page.ClientScript.GetPostBackEventReference(this, (page_Current + 1).ToString()) + "/" TYPE ='submit' name = " + this.UniqueID + " Value = '下一页' />");
}
writer.Write("</div>/n");
}
public static List<int> PostBackCount;
public void RaisePostBackEvent(string eventArgument)
{
try
{
this.Page_Current = Int32.Parse(eventArgument);
}
catch
{
this.page_Current = 1;
}
PageEventArgs e = new PageEventArgs();
e.NewPageIndex = page_Current;
PageChangeIndex(this, e);
}
/// <summary>
/// 定义委托,实现翻页时触发 事件
/// </summary>
/// <param name="sender">发送通知的对象</param>
/// <param name="args">包含所有接受者需要的附件信息</param>
public delegate void ItemPageIndexChanged(object sender, PageEventArgs args);
/// <summary>
/// 定义执行的事件
/// </summary>
public event ItemPageIndexChanged PageChangeIndex;
}
}
前台调用页面Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebCrm.Default" %>
<%@ Register Assembly="DBUtility" Namespace="DBUtility" TagPrefix="cc2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="test" runat="server">
<ItemTemplate>
<span><asp:Literal ID="wtitle" runat="server"></asp:Literal></span><br />
</ItemTemplate>
</asp:Repeater>
<cc2:Page01 ID="Page1" runat="server" Page_Count="10" />
</div>
</form>
</body>
</html>
后台代码default.aspx.cs
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using DBUtility;
using System.Collections.Generic;
namespace WebCrm
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SetValue();
}
this.Page1.PageChangeIndex += new Page01.ItemPageIndexChanged(Page1_PageChangeIndex);
//this.Page1.PageChangeIndex+=new EventHandler<DBUtility.PageEventArgs>(Page1_PageChangeIndex);
}
void Page1_PageChangeIndex(object sender, DBUtility.PageEventArgs args)
{
this.Page1.Page_Current = args.NewPageIndex;
SetValue();
}
private void SetValue()
{
int _records=0;
string sql = string.Format("select USERNAME from TBASEUSER");
IEnumerable<DataRow> rosList = DbHelperSQL.Query(sql, 15, this.Page1.Page_Current, out _records);
test.DataSource = DbHelperSQL.Query(sql,2,this.Page1.Page_Current, out _records);
test.ItemDataBound += new RepeaterItemEventHandler(test_ItemDataBound);
test.DataBind();
this.Page1.SetPage(2, _records);
}
void test_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
DataRow row = e.Item.DataItem as DataRow;
Literal wtitle = e.Item.FindControl("wtitle") as Literal;
wtitle.Text = row["USERNAME"].ToString();
}
}
}
}
再补上我们之前说的保存数据的对象PageEventArgs .cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBUtility
{
public class PageEventArgs : EventArgs
{
/// <summary>
/// 最新页面
/// </summary>
private int newpageindex;
/// <summary>
/// 属性设置最新页面的页码值
/// </summary>
public int NewPageIndex
{
get { return newpageindex; }
set { newpageindex = value; }
}
}
}
这样我们就完成了自定义分页控件的制作,很简单吧,希望大家多多指点。