科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件创建用于ASP.NET的分页控件

创建用于ASP.NET的分页控件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

解决向任何ASP.NET控件添加分页功能的问题。为开发复合ASP.NET控件提供了很多有用的提示和技巧。

作者:佚名 来源:Microsoft 2007年10月17日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
生成 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 中并从中进行还原。在数据绑定过程中,会验证和使用页面索引。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章