zoukankan      html  css  js  c++  java
  • [原创]ExtAspNet秘密花园(十六) — 表格之排序与分页

    排序和分页是表格必备的两个重要功能,本章会详细阐述如何在ExtAspNet中实现这两个功能。

    排序

    首先来看一个排序的例子,ASPX标签如下:

       1:   <ext:Grid ID="Grid1" Title="表格" AllowSorting="true" SortColumn="year"
       2:      SortDirection="ASC" Width="750px" AutoHeight="true" runat="server" EnableCheckBoxSelect="True"
       3:      DataKeyNames="Id,Name,AtSchool" EnableRowNumber="True" OnSort="Grid1_Sort">
       4:      <Columns>
       5:          <ext:BoundField Width="100px" ColumnID="name" SortField="Name" DataField="Name" DataFormatString="{0}"
       6:              HeaderText="姓名" />
       7:          <ext:TemplateField Width="60px" SortField="Gender" HeaderText="性别">
       8:              <ItemTemplate>
       9:                  <asp:Label ID="Label2" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></asp:Label>
      10:              </ItemTemplate>
      11:          </ext:TemplateField>
      12:          <ext:BoundField Width="100px" ColumnID="year" SortField="EntranceYear" DataField="EntranceYear" HeaderText="入学年份" />
      13:          <ext:CheckBoxField Width="60px" SortField="AtSchool" RenderAsStaticField="true" DataField="AtSchool"
      14:              HeaderText="是否在校" />
      15:          <ext:HyperLinkField HeaderText="所学专业" DataToolTipField="Major" DataTextField="Major"
      16:              DataTextFormatString="{0}" DataNavigateUrlFields="Major" DataNavigateUrlFormatString="http://gsa.ustc.edu.cn/search?q={0}"
      17:              DataNavigateUrlFieldsEncode="true" Target="_blank" ExpandUnusedSpace="True" />
      18:          <ext:ImageField Width="60px" DataImageUrlField="Group" DataImageUrlFormatString="~/images/16/{0}.png"
      19:              HeaderText="分组"></ext:ImageField>
      20:      </Columns>
      21:  </ext:Grid>

    这里面有几个关键点:

    • 表格控件设置排序相关的属性以及OnSort事件处理函数
      • AllowSorting:是否允许排序。
      • SortColumn:当前排序的列ID,当然也可以不设置此属性,而是在后台初始化代码中直接指定默认排序字段。
      • SortDirection:排序方向,ASC(默认值)或者DESC。
    • 对于每一个需要排序的列,设置SortField属性。

    来看下后台表格初始化代码:

       1:  protected void Page_Load(object sender, EventArgs e)
       2:  {
       3:      if (!IsPostBack)
       4:      {
       5:          BindGrid();
       6:      }
       7:  }
       8:   
       9:  private void BindGrid()
      10:  {
      11:      GridColumn column = Grid1.FindColumn(Grid1.SortColumn);
      12:      BindGridWithSort(column.SortField, Grid1.SortDirection);
      13:  }
      14:   
      15:  private void BindGridWithSort(string sortField, string sortDirection)
      16:  {
      17:      DataTable table = GetDataTable();
      18:   
      19:      DataView view1 = table.DefaultView;
      20:      view1.Sort = String.Format("{0} {1}", sortField, sortDirection);
      21:   
      22:      Grid1.DataSource = view1;
      23:      Grid1.DataBind();
      24:  }

    注意,在调用BindGridWithSort私有函数时,我们通过FindColumn找到默认排序的列,从而找到此列的排序数据字段。

    当然,如果没有设置表格的SortColumn,这里可以直接硬编码默认的排序字段,比如:

       1:  private void BindGrid()
       2:  {
       3:      BindGridWithSort("EntranceYear", Grid1.SortDirection);
       4:  }

    最后是用户点击列标题时触发的排序事件,来看下其事件处理函数:

       1:  protected void Grid1_Sort(object sender, ExtAspNet.GridSortEventArgs e)
       2:  {
       3:      BindGridWithSort(e.SortField, e.SortDirection);
       4:  }

    是不是非常简单,最后的显示效果如下:

    image

    内存分页

    所谓的内存分页,就是在页面初始化时将表格数据一次性全部载入,保存在页面状态视图中,从而保证在后续的分页操作时不用再次访问数据库。在数据量少的情况下(一般少于100条数据),这一方式非常划算,因此需要的编码非常少。下面还是通过一个示例来说明。

    先来看下ASPX标签的结构:

       1:  <ext:Grid ID="Grid1" Title="表格" PageSize="5" ShowBorder="true" ShowHeader="true"
       2:      AutoHeight="true" AllowPaging="true" runat="server" EnableCheckBoxSelect="True"
       3:      Width="800px" DataKeyNames="Id,Name" OnPageIndexChange="Grid1_PageIndexChange"
       4:      EnableRowNumber="True">
       5:      <Columns>
       6:          <ext:BoundField Width="100px" DataField="Name" DataFormatString="{0}" HeaderText="姓名" />
       7:          <ext:TemplateField Width="60px" HeaderText="性别">
       8:              <ItemTemplate>
       9:                  <asp:Label ID="Label2" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></asp:Label>
      10:              </ItemTemplate>
      11:          </ext:TemplateField>
      12:          <ext:BoundField Width="60px" DataField="EntranceYear" HeaderText="入学年份" />
      13:          <ext:CheckBoxField Width="60px" RenderAsStaticField="true" DataField="AtSchool" HeaderText="是否在校" />
      14:          <ext:HyperLinkField HeaderText="所学专业" DataTooltipField="Major" DataTextField="Major"
      15:              DataTextFormatString="{0}" DataNavigateUrlFields="Major" DataNavigateUrlFormatString="http://gsa.ustc.edu.cn/search?q={0}" DataNavigateUrlFieldsEncode="true"
      16:              Target="_blank" ExpandUnusedSpace="True" />
      17:          <ext:ImageField Width="60px" DataImageUrlField="Group" DataImageUrlFormatString="~/images/16/{0}.png"
      18:              HeaderText="分组"></ext:ImageField>
      19:      </Columns>
      20:  </ext:Grid>

    这里面有几个关键点:

    • 表格设置属性AllowPaging=true和PageSize;
    • 表格设置分页事件处理函数OnPageIndexChange;
    • 各列没有特殊的属性设置。

    看下后台初始化代码:

       1:  protected void Page_Load(object sender, EventArgs e)
       2:  {
       3:      if (!IsPostBack)
       4:      {
       5:          BindGrid();
       6:      }
       7:  }
       8:   
       9:  private void BindGrid()
      10:  {
      11:      DataTable table = GetDataTable();
      12:   
      13:      Grid1.DataSource = table;
      14:      Grid1.DataBind();
      15:  }

    可以看到,初始化代码和不分页时的代码一模一样。

    再来看下分页事件处理函数:

       1:  protected void Grid1_PageIndexChange(object sender, ExtAspNet.GridPageEventArgs e)
       2:  {
       3:      Grid1.PageIndex = e.NewPageIndex;
       4:  }

    也很简单,对吧。

    image

    其实,如果你之前用过AspNet的GridView的话,这里的代码和使用GridView的代码一模一样。

    数据库分页

    在展示大数据时,数据库分页是必须的。数据库分页时,页面第一次初始化时只加载表格当前页的数据,所以每次用户点击分页按钮时,后台代码都要进行数据库查询并重新绑定当前页的数据。由于查询当前页的数据并绑定表格需要反复调用,通常我们把这一操作提取到一个单独的函数中。

    首先看下ASPX标签的声明:

       1:  <ext:Grid ID="Grid1" Title="表格" Width="800px" PageSize="5" ShowBorder="true" ShowHeader="true"
       2:      AutoHeight="true" AllowPaging="true" runat="server" EnableCheckBoxSelect="True"
       3:      DataKeyNames="Id,Name" IsDatabasePaging="true" OnPageIndexChange="Grid1_PageIndexChange"
       4:      EnableRowNumber="True">
       5:      <Columns>
       6:          <ext:BoundField Width="100px" DataField="Name" DataFormatString="{0}" HeaderText="姓名" />
       7:          <ext:TemplateField Width="60px" HeaderText="性别">
       8:              <ItemTemplate>
       9:                  <asp:Label ID="Label2" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></asp:Label>
      10:              </ItemTemplate>
      11:          </ext:TemplateField>
      12:          <ext:BoundField Width="60px" DataField="EntranceYear" HeaderText="入学年份" />
      13:          <ext:CheckBoxField Width="60px" RenderAsStaticField="true" DataField="AtSchool" HeaderText="是否在校" />
      14:          <ext:HyperLinkField HeaderText="所学专业" DataTooltipField="Major" DataTextField="Major"
      15:              DataTextFormatString="{0}" DataNavigateUrlFields="Major" DataNavigateUrlFormatString="http://gsa.ustc.edu.cn/search?q={0}" DataNavigateUrlFieldsEncode="true"
      16:              Target="_blank" ExpandUnusedSpace="True" />
      17:          <ext:ImageField Width="60px" DataImageUrlField="Group" DataImageUrlFormatString="~/images/16/{0}.png"
      18:              HeaderText="分组"></ext:ImageField>
      19:      </Columns>
      20:  </ext:Grid>

    这里面有几个关键点:

    • 表格设置属性AllowPaging、IsDatabasePaging、PageSize三个属性;
    • 表格设置分页事件处理函数OnPageIndexChange;
    • 各列没有特殊的属性设置。

    看下后台初始化代码:

       1:  protected void Page_Load(object sender, EventArgs e)
       2:  {
       3:      if (!IsPostBack)
       4:      {
       5:          BindGrid();
       6:      }
       7:  }
       8:   
       9:  private void BindGrid()
      10:  {
      11:      // 1.设置总项数
      12:      Grid1.RecordCount = GetTotalCount();
      13:   
      14:      // 2.获取当前分页数据
      15:      DataTable table = GetPagedDataTable(Grid1.PageIndex, Grid1.PageSize);
      16:   
      17:      // 3.绑定到Grid
      18:      Grid1.DataSource = table;
      19:      Grid1.DataBind();
      20:  }

    可以看出初始化表格数据需要如下几个步骤:

    1. 设置表格的RecordCount属性,告诉表格总记录数;
    2. 根据表格的PageIndex(默认是0)和PageSize属性,从数据库查询本页的数据;
    3. 将查询到的本页数据绑定到表格。

    由此可以看出,表格必须知道如下四种数据后,才能正确显示:

     

      • 当前是第几页(PageIndex);
      • 总共有多少条数据(RecordCount);
      • 每页显示多少条数据(PageSize);
      • 当前页的数据是什么(DataSource)。

    再来看下分页事件处理函数:

       1:  protected void Grid1_PageIndexChange(object sender, ExtAspNet.GridPageEventArgs e)
       2:  {
       3:      Grid1.PageIndex = e.NewPageIndex;
       4:   
       5:      BindGrid();
       6:  }

    首先告诉表格接下来应该显示哪一页,然后重新查询数据库并绑定当前页的数据。

    界面显示效果和内存分页时一样,就不再截图。

    为什么说内存分页在大数据时性能差?

    其实原因前面已经提到了,主要是因为内存分页时会把所有表格数据保存到页面的状态视图中(ViewState),导致页面大小迅速增加,从而增加网络下载上载的时间,并且减慢了页面的渲染速度。

    虽然ExtAspNet放弃了在ViewState中保存数据,从而可以在Ajax的环境中减少网络的数据传输量,但是内存分页时所有的表格数据还是要保存下来,供下次分页时使用。

    拿本篇文章中的内存分页示例,在用户点击下一页时,通过FireBug可以看到这次HTTP Post请求:

    image

    其中X_STATE就是ExtAspNet保存控件状态的地方,把全部X_STATE的内容拷贝下来,并执行如下JavaScript代码:

       1:  var xstate = JSON.parse(Base64.decode('eyJHcmlk...FtdXX19'));
       2:  var values = xstate.Grid1.X_Rows.Values;
       3:  values.length + '\r\n' + JSON.stringify(values);

    可以看到如下的执行结果:

    image

    由此可见,全部的11条数据在每次页面回发时都会作为HTTP Post的参数上传到服务器,从而在大数据量的情况下导致页面性能急剧下降。

    小结

    排序和分页是表格的最基本操作,也是每个程序员都应该熟练掌握的知识。特别是处理大量数据(一般大于100条)一定要使用数据库分页,否则页面性能会非常差。下一篇文章我们会讨论ExtAspNet对表格的扩展列,包括序号列、选择框列、行扩展列、模拟树列以及弹出窗体列。

    注:《ExtAspNet秘密花园》系列文章由三生石上原创,博客园首发,转载请注明出处。文章目录 官方论坛

  • 相关阅读:
    价格与用户权限
    bootstrap-validator
    关于项目管理的感想
    rabbitmq使用日记
    matplotlib
    JS滑动到页面底部
    排序算法思想
    杀死指定进程
    pycharm的一些快捷键
    对支付宝支付的理解
  • 原文地址:https://www.cnblogs.com/sanshi/p/2712170.html
Copyright © 2011-2022 走看看