创建用于 ASP.NET 的分页程序控件(二)

翻译|其它|编辑:郝浩|2005-03-09 10:13:00.000|阅读 1494 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>


生成 SqlPager 控件

将作为复合控件来生成 SqlPager 控件并让其继承 WebControl 类。复合控件是 ASP.NET 服务器控件所特有的,它是由一个或多个服务器控件组成。

public class SqlPager : WebControl, INamingContainer
{ ... }


除非生成完全自定义的控件或扩展现有的控件,否则,创建新控件时,大多数时间实际上是在生成复合控件。要创建 SqlPager,组合一个 Table 控件,并根据分页程序的样式,组合几个 LinkButton 控件或者一个 DropDownList 控件。

生成复合控件时,需要注意几条原则。首先,需要覆盖 CreateChildControls protected 方法。CreateChildControls 方法是从 Control 继承来的,当服务器控件为了显示而要创建子控件时或在返回后,将调用此方法。

protected override void CreateChildControls()
{
// 清除现有的子控件及其 ViewState
Controls.Clear();
ClearChildViewState();

// 生成控件树
BuildControlHierarchy();
}


覆盖此方法时,需要执行几项重要的操作。创建并初始化任何所需的子控件实例并将它们添加到父控件的 Controls 集合中。但是,生成新控件树之前,应该删除任何现有的子控件并清除子控件可能留下的任何 ViewState 信息。

复合组件还需要实现 INamingContainer 接口,以便 ASP.NET 运行时可以为其创建一个新的命名范围。这就确保了复合控件中的所有控件都具有唯一的名称。这还将确保能够自动处理子控件的返回数据。

对于 SqlPager 控件来说,成为命名容器非常重要。事实上,SqlPager 包含一些 LinkButton 控件,并且需要获取并处理其单击事件以便导航页面。正如 ASP.NET 页面中的任何其他控件一样,LinkButton 也被赋予了一个 ID,用于标识处理返回事件的控件。

处理返回事件时,ASP.NET 运行时试图查找事件的目标 ID 与主窗体的任何直接子控件之间是否存在匹配关系。LinkButton 是分页程序的子控件,因此不能运行其服务器端的代码。这是否意味着只有窗体的直接子控件才能启动并处理服务器事件?当然不是,只要您使用命名容器。

通过使 SqlPager 控件实现 INamingContainer 接口,可以将嵌入式链接按钮的实际 ID 从“First”更改为“SqlPager1:First”。当用户单击以查看新页面时,返回事件将 SqlPager1:First 作为目标控件。实际上,运行时用来识别目标控件的算法比上面介绍的要复杂一些。运行时将事件目标控件的名称看作是用冒号分隔开的字符串。实际上,这种匹配是在窗体的子控件和用冒号分隔开的字符串(如 SqlPager1:First)的第一个标记之间进行的。由于分页程序是窗体的子控件,因此匹配时会成功,分页程序获取单击事件。如果您认为这种解释不够充分或者令人费解,只要下载 SqlPager 控件的源代码,删除 INamingContainer 标记接口并进行重新编译即可。您将看到分页程序能够返回,但不能内部处理单击事件。

INamingContainer 接口是一个不具备方法的标记接口,其实现只需在类声明中指定名称即可,无需进行任何其他操作。

复合控件的另一个重要方面是,它们通常不需要自定义逻辑来进行显示。复合控件的显示遵循其组成控件的显示。生成复合控件时,通常无需覆盖 Render 方法。

控件的 SqlPager 树由一个包含两个单元格的单行表格组成。该表格继承了分页程序的大部分可视设置,如前景颜色和背景颜色、边框、字体信息和宽度等。第一个单元格包含导航条,其结构取决于 PagerStyle 属性的值。如果分页程序的样式为 NextPrev,则导航条将由四个 VCR 式的按钮组成。否则,它将由一个下拉列表组成。

private void BuildControlHierarchy()
{
// 生成环境表格(一行,两个单元格)
Table t = new Table();
t.Font.Name = this.Font.Name;
t.Font.Size = this.Font.Size;
t.BorderStyle = this.BorderStyle;
t.BorderWidth = this.BorderWidth;
t.BorderColor = this.BorderColor;
t.Width = this.Width;
t.Height = this.Height;
t.BackColor = this.BackColor;
t.ForeColor = this.ForeColor;

// 生成表格中的行
TableRow row = new TableRow();
t.Rows.Add(row);

// 生成带有导航条的单元格
TableCell cellNavBar = new TableCell();
if (PagerStyle == this.PagerStyle.NextPrev)
BuildNextPrevUI(cellNavBar);
else
BuildNumericPagesUI(cellNavBar);
row.Cells.Add(cellNavBar);

// 生成带有页面索引的单元格
TableCell cellPageDesc = new TableCell();
cellPageDesc.HorizontalAlign = HorizontalAlign.Right;
BuildCurrentPage(cellPageDesc);
row.Cells.Add(cellPageDesc);

// 将表格添加到控件树
this.Controls.Add(t);
}


将各个控件添加到正确的 Controls 集合对于分页程序的正确显示极其重要。最外层的表格必须添加到分页程序的 Controls 集合中。链接按钮和下拉列表必须添加到相应表格单元格的 Controls 集合中。

下面给出了用来生成链接按钮导航条的代码。每个按钮都显示有一个 Webdings 字符,可以根据需要禁用,并被绑定到内部的 Click 事件处理程序。

private void BuildNextPrevUI(TableCell cell)
{
bool isValidPage = ((CurrentPageIndex >=0) &&
(CurrentPageIndex <= TotalPages-1));
bool canMoveBack = (CurrentPageIndex>0);
bool canMoveForward = (CurrentPageIndex<TotalPages-1);

// 显示 << 按钮
LinkButton first = new LinkButton();
first.ID = "First";
first.Click += new EventHandler(first_Click);
first.Font.Name = "webdings";
first.Font.Size = FontUnit.Medium;
first.ForeColor = ForeColor;
first.ToolTip = "第一页";
first.Text = "7";
first.Enabled = isValidPage && canMoveBack;
cell.Controls.Add(first);
:
}


分页程序的另一种样式(在下拉列表中列出数字页面)的生成方法如下所示:

private void BuildNumericPagesUI(TableCell cell)
{
// 显示一个下拉列表
DropDownList pageList = new DropDownList();
pageList.ID = "PageList";
pageList.AutoPostBack = true;
pageList.SelectedIndexChanged += new EventHandler(PageList_Click);
pageList.Font.Name = this.Font.Name;
pageList.Font.Size = Font.Size;
pageList.ForeColor = ForeColor;

if (TotalPages <=0 || CurrentPageIndex == -1)
{
pageList.Items.Add("No pages");
pageList.Enabled = false;
pageList.SelectedIndex = 0;
}
else // 填充列表
{
for(int i=1; i<=TotalPages; i++)
{
ListItem item = new ListItem(i.ToString(), (i-1).ToString());
pageList.Items.Add(item);
}
pageList.SelectedIndex = CurrentPageIndex;
}
}


所有事件处理程序(Click 和 SelectedIndexChanged)最终都会更改当前显示的页面。这两种方法都会调用一个公用的 private 方法 GoToPage。

private void first_Click(object sender, EventArgs e)
{
GoToPage(0);
}
private void PageList_Click(object sender, EventArgs e)
{
DropDownList pageList = (DropDownList) sender;
int pageIndex = Convert.ToInt32(pageList.SelectedItem.Value);
GoToPage(pageIndex);
}
private void GoToPage(int pageIndex)
{
// 准备事件数据
PageChangedEventArgs e = new PageChangedEventArgs();
e.OldPageIndex = CurrentPageIndex;
e.NewPageIndex = pageIndex;

// 更新当前的索引
CurrentPageIndex = pageIndex;

// 启动页面更改事件
OnPageIndexChanged(e);

// 绑定新数据
DataBind();
}
 

其他导航按钮的处理程序与 first_Click 的区别仅在于它们传递给 GoToPage 方法的页码不同。GoToPage 方法负责处理 PageIndexChanged 事件,并负责启动数据绑定过程。它准备事件数据(旧页面和新页面索引)并触发事件。GoToPage 被定义为 private,但是可以使用 CurrentPageIndex 属性通过编程的方式更改显示的页面。

public int CurrentPageIndex
{
get {return Convert.ToInt32(ViewState["CurrentPageIndex"]);}
set {ViewState["CurrentPageIndex"] = value;}
}
 

与表 1 中所列的所有属性一样,CurrentPageIndex 属性的实现方法也相当简单。它将其内容保存到 ViewState 中并从中进行还原。在数据绑定过程中,会验证和使用页面索引。

 


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP