본문 바로가기

TechLog

GridView의 페이징 커스터마이징 하기



ASP.NET의 GridView에서 제공하는 페이징 기능을 사용할 경우, 내부적으로 DB를 쿼리할 때마다 데이터 전체를 읽어들이게 하므로 대상 데이터의 양이 많아지면 사용하기가 좀 껄끄러워진다. 데이터의 양이 많은 테이블에서 레코드를 읽어올 경우 화면 표시될 레코드만 페이지 단위로 가져오는 쿼리를 수행해서 성능 향상을 꾀하여야 하는데, 이럴 경우 Command 를 사용해서 임의의 데이터 페이징을 구현할 수 있다.


- aspx 페이지의 GridView 태그
   1: <asp:GridView ID="GridView1" runat="server" AllowPaging="True" CellPadding="4" 
   2:     ForeColor="#333333" GridLines="Both" Width="100%" OnDataBound="GridView1_DataBound">
   3:     <RowStyle BackColor="white" />
   4:     <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
   5:     <PagerTemplate>
   6:         <asp:LinkButton ID="btnFirst" CommandName="Page" Text="처음" OnCommand="btn_Command" runat="server"/>
   7:         <asp:LinkButton ID="btn0" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
   8:         <asp:LinkButton ID="btn1" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
   9:         <asp:LinkButton ID="btn2" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  10:         <asp:LinkButton ID="btn3" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  11:         <asp:LinkButton ID="btn4" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  12:         <asp:LinkButton ID="btn5" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  13:         <asp:LinkButton ID="btn6" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  14:         <asp:LinkButton ID="btn7" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  15:         <asp:LinkButton ID="btn8" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  16:         <asp:LinkButton ID="btn9" CommandName="Page" Visible="false" OnCommand="btn_Command" runat="server"/>
  17:         <asp:LinkButton ID="btnLast" CommandName="Page" Text="끝" OnCommand="btn_Command" runat="server"/>
  18:     </PagerTemplate>
  19:     <PagerStyle BackColor="#EFF3FB" ForeColor="White" HorizontalAlign="Center" />
  20:     <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
  21:     <HeaderStyle BackColor="#E7EFF7" Font-Bold="True" ForeColor="White" HorizontalAlign="Center" />
  22:     <EditRowStyle BackColor="#2461BF" />
  23:     <AlternatingRowStyle BackColor="White" />
  24: </asp:GridView>

- cs 파일의 내용
   1: protected void btn_Command(object sender, CommandEventArgs e)
   2: {
   3:     switch (e.CommandName)
   4:     {
   5:         case "Page":
   6:             pageIndex = int.Parse((string)e.CommandArgument);
   7:             DataBind();    // 쿼리 수행 및 바인딩 수행 함수
   8:             break;
   9:     }
  10: }
  11:  
  12:  
  13: protected void GridView1_DataBound(object sender, EventArgs e)
  14: {
  15:     GridViewRow gvrPager = GridView1.BottomPagerRow;
  16:     if (gvrPager == null) return;
  17:     gvrPager.Visible = true;
  18:     
  19:     string datasetTableName = "POS_GCMI_IO_TRANSACTION_HIST_COUNT";
  20:  
  21:  
  22:     // SQL ; 레코드 건수 가져오는 쿼리
  23:     string strSQL =
  24:         "select count(*) FROM   POS_GCMI_IO_TRANSACTION_HIST A ";
  25:  
  26:  
  27:     dataSet = oracleLib.ExeSQLReturnDataset(CommandType.Text, strSQL, dataSet, datasetTableName);
  28:     rowCount = int.Parse(dataSet.Tables[datasetTableName].Rows[0][0].ToString());
  29:     pageCount = (rowCount - 1) / 10 + 1;
  30:  
  31:  
  32:     LinkButton btn;
  33:  
  34:  
  35:     btn = (LinkButton)gvrPager.Cells[0].FindControl("btnFirst");
  36:     btn.CommandArgument = "0";
  37:     btn = (LinkButton)gvrPager.Cells[0].FindControl("btnLast");
  38:     btn.CommandArgument = (pageCount - 1).ToString();
  39:  
  40:  
  41:     for (int i = 0; i<10; i++)
  42:     {
  43:         btn = (LinkButton)gvrPager.Cells[0].FindControl("btn" + i.ToString());
  44:         int currentindex = pageIndex + i - 5;
  45:         if (currentindex >= pageCount || currentindex < 0) continue;
  46:         btn.Text = (currentindex + 1).ToString();
  47:         btn.CommandArgument = currentindex.ToString();
  48:         btn.Visible = true;
  49:         if (i == 5) btn.Enabled = false;
  50:     }
  51:  
  52:  
  53:     lblCount.Text = string.Format(
  54:         "총건수 : {0} 건 / {1} 페이지 중 {2} 페이지", rowCount.ToString("#,0"), pageCount.ToString("#,0"), (pageIndex + 1).ToString("#,0"));
  55: }
  56:  
  57:  
  58: void DataBind() 
  59: {
  60:     // dataSet - POS_GCMI_IO_TRANSACTION_HIST
  61:     string datasetTableName = "POS_GCMI_IO_TRANSACTION_HIST";
  62:     // SQL ; 내용
  63:     string strSQL = 
  64:         string.Format("select * from " +
  65:         "(SELECT rownum rn, * FROM POS_GCMI_IO_TRANSACTION_HIST A) " +
  66:         "where rn between {0} and {1}", pageIndex * 10 + 1, pageIndex * 10 + 10);
  67:  
  68:  
  69:     dataSet = oracleLib.ExeSQLReturnDataset(CommandType.Text, strSQL, dataSet, datasetTableName);
  70:     
  71:     GridView1.DataSource = dataSet.Tables[datasetTableName];
  72:     GridView1.DataBind();
  73: }

많은 부분이 생략된 코드이기는 한데 .. 코드를 살펴보면 대충 기본 아이디어는 파악할 수 있을 것이다. 열 개의 페이징 링크를 미리 aspx 페이지에 정의해두고, GridView에 데이터가 바인딩되는 시점에서 페이지의 이동에 따라 보여줄 페이징 링크 및 페이지의 숫자를 결정한다. 페이지 링크를 클릭하면 btn_Command가 호출되어 페이지 인덱스 값을 설정하고, 최종적으로 DataBind() 함수에서 설정된 페이지 인덱스 값을 설정하여 페이징을 수행하게 된다. (지금 여기에서는 오라클 DB를 상정하고 rownum을 사용한 페이징을 사용했다)

이런 방식으로 GridView의 기본 Pager 컨트롤 및 내부 페이징 로직 대신, 커스터마이징 된 페이징 컨트롤(여기에서는 여러개의 컨트롤을 사용하고 있지만)과 페이징 쿼리를 사용할 수 있다.