login register Sysop! about ME  
qrcode
    최초 작성일 :    2004년 05월 25일
  최종 수정일 :    2004년 05월 25일
  작성자 :    taeyo
  편집자 :    Taeyo (김 태영)
  읽음수 :    56,920

강좌 목록으로 돌아가기

필자의 잡담~

여름이 오고 있습니다.... 농구하기에 좋은 날씨가 되었네염~~~ 좀 덥긴하지만 말입니당~ ^^

대상 : ASP.NET을 이용하여 스스로 일반 게시판이 작성가능하거나,
         Taeyo's ASP.NET v1.0 서적을 통해서 게시판 만들기를 이미 공부하신 분

자. 이제 계층형 출력도 완성이 되지 않았습니까? 그렇다면, 이번 시간에는 이제 페이징을 완전하게 구성하여 List.aspx 페이지를 완성해 보도록 하겠습니다. (과중한 업무에 치이다보니 눈을 비비면서 강좌를 쓰고 있답니다 *_*;; 격려의 의미로 박수 한번. 짝~!!!)

일단, 현재의 상황에서는 페이징을 위해서 두 가지 방식을 사용할 수 있는데요. 한가지는 여러분이 알고 계시는 방법(DataGrid에서 쓰는 방법)을 사용하여직접 DataGrid의 페이징을 사용할 수도 있구요. 아니면, 태오 사이트에서 제공하는 PagingHelper 컨트롤을 사용해서 페이징 바를 좀 더 이쁘게 구성하는 방법이 있을 수 있습니다.

여기서는 저번 시간에 말씀드린대로 PagingHelper 컨트롤을 사용해서 페이저 바(Pager Bar)를 멋드러지게 꾸며볼까 합니다.. ^^ 아마도, 대부분의 여러분들은 이전 시간에알려드린 PagingHelper 컨트롤 사용법 링크를 모두 읽어보셨을 것이라 생각됩니다. 물론, 말 안듣는 분들 꼭 계십니다. 하하하... 뭐 개별적으로 공부 안하신 분들도 괜찮습니다. 어차피 이번 시간에 다시금 자세하게 설명드릴 것이니까요... 라고 이야기 할줄 알았나요?

네버 안됩니다. 그것은 안되지요. 만일, PagingHelper 컨트롤의 사용법을 아직까지 공부하지 않으신 분은 얼렁 공부해 주시기 바랍니다. 강좌를 따라하시다보면그 사용법이 DataGrid 컨트롤의 페이징 다루는 것과 그리 차이가 없다는 것을 아시게 될 것이기에, 공부하는 데에 그렇게 많은 시간이 걸리지는 않을 것입니다.

다시 한번 알려드리면 PagingHelper 컨트롤의 사용법을 알려드리는 강좌는 다음과 같습니다. ^^ (사실, 컨트롤을 웹 폼 위에 올려놓기만 하신다면, 사용하는 방법은 뭐 그 강좌를 읽어보지 않아도 따라하실 수 있을 겁니다. 하지만, 완전하게 다루기 위해서는 한번쯤은 봐 두실 필요가 있습니다. 부탁드립니다!!! -_-;)

PagingHelper 컨트롤의 사용법

저는 여러분이 이 강좌를 이미 따라하셨다는 가정하에서 진행해보도록 하겠습니다.

일단, PagingHelper 컨트롤을 사용할 경우에 여러분이 설정해 주어야 하는 단계를 다시 한번 정리하고 진행해 보도록 하겠습니다.강좌를 보셨으면 아시겠지만, PagingHelper 컨트롤을 사용하려면 다음과 같은 설정을 해주면 됩니다.

1. PagingHelper 컨트롤을 웹 폼에 올려놓는다.
2. 웹 폼 페이지의 쿼리를 페이징이 가능한 쿼리로 변경한다.
3. PagingHelper 컨트롤의 PageSize 속성과 VirtualItemCount 속성을 지정한다.
4. PagingHelper 컨트롤의 PageIndexChanged 이벤트 처리기를 작성한다.

그렇습니다. 쉽습니다. ^^ 1번의 경우는 정말로 쉽구요. 2번의 경우는 이미 우리가 해 둔 상태입니다. 실제로 우리가 해야할 작업은 3번과 4번 정도 밖에는 없다는 것이지요

그렇다면, 우선 List.aspx 페이지에 PagingHelper 컨트롤을 한번 올려놔 볼까요?그 컨트롤을 올려놓을 공간은 이전 시간에 페이징 테스트를 위해서 TextBox와 Button을 올려놓았던 바로 그 자리!! 로 하도록 하겠습니다.일단, 이전 시간에 추가했던 TextBox와 Button을 과감하게 삭제하시구요. 그 위에 PagingHelper 컨트롤을 멋드러지게 드래그 앤 드롭으로 올려놓아 보세요

그러면, HTML 코드는 아마도 대략 다음과 같이 구성되어질 것입니다. ^^ (저는 HTML을 조금 다듬어서, 실제 List와 PagingHelper 컨트롤 구역사이에 구분 간격도 두어보았습니다. 취향에 따라 여러분도이렇게 지정하셔도 좋을 듯 합니다. ^^)

                                // 기존 코드들
                                // ...................

                                <asp:BoundColumn DataField="readcount" HeaderText="읽음">
                                    <HeaderStyle HorizontalAlign="Center" Width="40px">
                                            </HeaderStyle>
                                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
                                </asp:BoundColumn>
                            </Columns>
                        </asp:DataGrid>
                    </td>
                </tr>
                <tr class="txt01">
                    <td bgColor="#dadada" height="2"></td>
                </tr>
                <tr>
                    <td align="right" height="30">
                        <taeyo:PagingHelper id="PagingHelper1" runat="server"></taeyo:PagingHelper>
                    </td>
                </tr>
            </table>
        </form>
    </body>
</HTML>

이제, PagingHelper 컨트롤을 웹 폼에 올려놓았고, 페이징을 위한 쿼리도 이미 준비되어져 있으니, 3번 단계로 진행하면 되겠네요.

3번 단계는PagingHelper 컨트롤의 PageSize 속성과 VirtualItemCount 속성을 지정하는 것입니다. DataGrid 컨트롤의 페이징을 이용할 경우에도 동일하게 이 작업은 필요하지요???즉, 페이징을 제대로 구성하기 위해서는 PageSize 값과 함께 반드시 전체 페이지 카운트 값인 VirtualItemCount도 예외없이 반드시 지정해 주어야 한다는 것입니다.

하지만, VirtualItemCount 값은 데이터베이스에 쿼리를 날려서 그 값을 얻어오지 않는 한, 알아올 수 없습니다. 해서, 제 Taeyo's ASP.NETwith C# 책에 보시면 이를 위해서 별도의 쿼리를 한번 더 날리고 있는 것을 보실 수 있을 것입니다. 이미 그 책을 보시고 공부하신 분이라면 같은 방법으로작성해 주셔도 무방하긴 합니다만.. 이제 이 강좌를 보실 즈음이면 초급자는 서서히 떼어가고 있는 상황일테니, 그 방법보다는 조금 더 나은 방법을 사용하시는 것이나을 것 같네요 ^^ 해서, 제가 이전 시간에 저장 프로시저에서 전체 레코드 카운트를 OUTPUT 매개변수로써 제공한 것입니다.

다시 말해서, UP_SELECT_BOARDLIST_PAGING 프로시저의

@TotalRowCount int OUTPUT

라는 인자가 바로 이러한 이유로 작성되었었다는 것입니다. ^^

자. 그렇다면, 이제 우리가 기존에 작업했던 내용에 이미 모든 준비가 다 되어져 있었다는 것을 알았으니, PagingHelper 컨트롤의 PageSize 속성과 VirtualItemCount 속성을 본격적으로 지정해보도록 하겠습니다. 다음 코드는 코드 비하인드의 Page_Load()와 Listing() 함수를 그에 맞게 조정한 코드입니다.(파란색 코드가 기존 코드에서 추가된 부분입니다)

    public class list_Paging : System.Web.UI.Page
    {
        //.. 기존 코드 ..
        protected int PageNo = 1;
        protected const int PageSize = 10;

        private void Page_Load(object sender, System.EventArgs e)
        {
            // 여기에 사용자 코드를 배치하여 페이지를 초기화합니다.
            if(!IsPostBack)
            {
                PagingHelper1.PageSize = PageSize;
                Listing();
            }
            Response.Cookies["ThreadBoard"]["UpdateReadCount"] = "0";
        }

        private void Listing()
        {
            string ConnectStr = "server=(local);database= TEST;userid=sa;password=xodh";

            SqlConnection Con = new SqlConnection(ConnectStr);
            SqlCommand Cmd = new SqlCommand();
            Cmd.Connection = Con;
            Cmd.CommandText = "UP_SELECT_BOARDLIST_PAGING";
            Cmd.CommandType = CommandType.StoredProcedure;

            //----------------- 계층형 추가 구역 -----------------
            Cmd.Parameters.Add("@Page", SqlDbType.Int);
            Cmd.Parameters["@Page"].Value = PageNo;
            Cmd.Parameters.Add("@PageSize", SqlDbType.Int);
            Cmd.Parameters["@PageSize"].Value = PageSize;

            Cmd.Parameters.Add("@TotalRowCount", SqlDbType.Int);
            Cmd.Parameters["@TotalRowCount"].Direction = ParameterDirection.Output;
            //----------------- 계층형 추가 구역 -----------------

            SqlDataAdapter adp = new SqlDataAdapter(Cmd);
            DataSet ds = new DataSet();

            adp.Fill(ds, "ThreadBoard");
            DataGrid1.DataSource = ds;
            DataGrid1.DataBind();

            PagingHelper1.VirtualItemCount = (int)Cmd.Parameters["@TotalRowCount"].Value;>

            Cmd = null;
            Con = null;
        }

        //.. 기존 코드 ..

PagingHelper 컨트롤의 PageSize 속성의 값은 ViewState에 의해 포스트백시에 그 값이 유지되기에, 페이지가 처음 로드되는 경우(!IsPostBack)에만 지정해 주시면 됩니다. 해서, 그 부분의 코드는 Page_Load 이벤트 내에서 if(IsPostBack) 인 경우에만 지정하도록 작성되어 있습니다.

하지만, VirtualItemCount의 경우는 그와는 달리 약간의 기다림(?)이 필요한데요.. 이는 이 값의 경우, 저장 프로시저가 수행된 다음 얻어낼 수 있는 값이기 때문에 그렇습니다. 해서,코드에서는 그 설정 위치가 Listing() 메서드 내부에서, 프로시저를 수행하여 바인딩을 한 다음에 설정하고 있는 것을 보실 수 있습니다. 저장 프로시저의 출력 매개변수(OUTPUT parameter)는 프로시저가 수행된 다음에만 값이채워지기에 그 위치에 코드를 작성한 것이지요 ^^ 만일, 그보다 이전 위치에서 그 값을 읽어본다면, 값이 없는 것을 확인하실 수 있을 겁니다 ^^. 고로, 이 속성의 경우는 코드 상에서 그 위치가 아주 중요합니다. 중요체크!!! 기억해 주세염~~~

자. 여기까지 되었나요?? 그렇다면, 일단 실행해서 페이저바가 제대로 출력되어 나오는지만 우선 테스트해 보도록 해요~~~

호오.. 좋죠??? 그렇습니다. 아주 잘 화면에 출력되고 있습니다. 단지, 페이저 구역에 있는 페이지 링크들을 클릭해봐야 아무런 반응이 없다는 것을 제외한다면 말입니다.

성급하신 분들은 링크를 클릭해도 아무런 반응이 없다고 성을 내실런지도 모르겠네요. 그렇다면, 슬픔입니다... 지금부터 하려는 것이 바로 그것인데, 쬐꼼 성급하셨던 것이니까요. 성급함의 진수를 가지신 분들이라면게시판에 질문까지 하실런지도 모르겠네요 "PagingHelper 컨트롤이 이상합니다. 동작 안해요~~~ ㅠㅠ" 라는 제목으로 말입니다 하하하~~~!!!! (-_-++ 웃고는 있지만, 실제로 이런 분 있었습니다 -_-;;)

그럼, 시작해 볼까요? 웹 폼 디자이너 모드에서 다음과 같이 PagingHelper 컨트롤을 선택하시구요. [속성] 창에서 을 클릭해 보세요.그러면, 여러 이벤트 목록이 나올텐데요. 그 중 OnPageIndexChanged라는 이벤트를 선택하신 다음, 우측 영역을 다음과 같이 더블 클릭해 보도록 하세요.

그러면, 코드 비하인드로 저절로 전환되고, 다음과 같은 코드 구역이 생겨날 것입니다. ^^

private void PagingHelper1_OnPageIndexChanged(object sender, TaeyoNetLib.PagingEventArgs e)
{

}

이 구역에 다음과 같은 코드를 작성해 보겠습니다. 이 코드는 현재 사용자가 선택한 페이지 링크의 인덱스 번호(e.PageIndex)를 가져와서, 그 인덱스 값에 +1을한 값을 현재 페이지 번호용 전역변수(PageNo)에 일단 담고 말입니다. 이어서, 다시금 그리드를 갱신하는 것입니다요. 다음과 같이 말입니다. 

private void PagingHelper1_OnPageIndexChanged(object sender, TaeyoNetLib.PagingEventArgs e)
{
    PageNo = e.PageIndex + 1;
    Listing();
}

이제 다시금 실행해 보도록 하세요 ^^ 그러면, 다음 그림과 같이 각각의 페이지로 잘 이동할 것입니다. ^^글쵸???

핫핫핫... 이쁘네요 ^^

근데, 아쉬운 것이 하나 있다면, 현재의 상태로는 페이지에 페이지 정보가 출력되고 있지 않기에, 현재 페이지가 몇 페이지인지, 총 페이지는 몇 페이지인지.. 알아보기가 쉽지 않습니다.해서, 그러한 정보가 페이지의 상단에서 출력되어진다면 더욱 보기에 좋겠죠??? 그렇다면, 그러한 기능을 하나 추가해 보도록 해요~~

다음처럼 list.aspx 페이지의 상단에 <tr>를 하나 더 추가하구요. 그 안에 [현재 페이지 / 총 페이지]를 나타낼 Label 컨트롤을 하나 올려보도록 해요. 그러면, HTML 코드는 다음과 같아질 겁니다.

    .. 중략 ..

    <body MS_POSITIONING="FlowLayout">
        <form id="list" method="post" runat="server">
            <table cellSpacing="0" cellPadding="0" width="520" border="0">
                <tr>
                    <td align="right" height="25">
                        <asp:Label Runat="server" ID="PageInfo"></asp:Label>
                    </td>
                </tr>
                <tr>
                    <td bgColor="#336699"></td>
                </tr>
                <tr>
                    <td bgColor="#668fcd"></td>
                </tr>
            </table>

    .. 중략 ..

그리고, 코드 비하인드 모드로 이동해서 Listing() 함수에다가... 방금 전에 올린 Label 컨트롤에 페이지 값 정보를 출력하는 코드를 작성해 보도록 해요~

        private void Listing()
        {

            //.. 기존 코드 ..

            //----------------- 계층형 추가 구역 -----------------

            SqlDataAdapter adp = new SqlDataAdapter(Cmd);
            DataSet ds = new DataSet();

            adp.Fill(ds, "ThreadBoard");
            DataGrid1.DataSource = ds;
            DataGrid1.DataBind();

            PagingHelper1.VirtualItemCount = (int)Cmd.Parameters["@TotalRowCount"].Value;>

            int PageCount = ((int)Cmd.Parameters["@TotalRowCount"].Value - 1) / PageSize + 1;
            PageInfo.Text = string.Format("({0}/{1}) Page", PageNo.ToString(), PageCount);

            Cmd = null;
            Con = null;
        }

        //.. 기존 코드 ..

총 페이지 수를알아내기 위해서 (전체 레코드 수 - 1) / 한 페이지의 크기 + 1 이라는 연산을 수행하는 부분이 있지요?? 사실 이것은 이젠 상당히 많이알려진 방법이기에 굳이 설명을 드릴 필요는 없어보입니다. 거의 공식처럼 사용되고 있어서요. 하지만, 설명을 안하면 슬픔에 잠기시는 분들도 있지요. 핫핫핫~~!!

해서 설명드리자면, ^^;; 이 공식은 총페이지 수를 얻어내기 위한 가장 간단하면서도 확실한 공식이랍니다. 의심나시면 한번 이 공식이 제대로 동작하는 지 테스트해 보세요 ^^    

단, 이 공식이제대로 동작하기 위해서는 일단 나눗셈을 한 다음의 모든 나머지는 버림(!) 되어야 하는데요.. 이 부분은 걱정할 것이 없는 것이, Integer 연산을 수행하면 자동으로 소수점이하는 버림으로 처리되기 때문입니다. 실은, integer의 그러한 연산 결과로 인해 태오난 아니 태어난 공식이 바로 위의 것이지요. ^^;;; 하하하..

위의 공식대로라면 전체 레코드가 21개일 경우(3 페이지가 나와야 할 것임),

(21 - 1) / 10 + 1 = 3

과 같이 됩니다. (20/10) + 1 즉, 2 + 1 과 같은 것이니까요...

20인 경우에는 어떻게 될까요? 그 경우, 결과는 2 페이지가 나와야 하겠죠?

(20 - 1) /10 + 1

이것은 (19/10) + 1 과 동일한데, 19/10의 결과는 1.9 입니다만, int 연산을 하게 되면 기본적으로 나머지는 버리게 됩니다. 고로, 이 연산은 1 + 1 과 같아지게 되고결과로는 2 가 나오게 되지요~~

이런 식으로 위의 공식은 우리가 원하는 결과를 완벽하게 얻을 수 있게 해준 답니다. 가급적 이해하시려 노력하시구요. 이해가 안가시면 암기!!! 간만에 암기 하나!! 나쁘지 않죠??? 아침 출근시간~~~ 네~~ 암기하나 머리에 꽂아주시면서 워킹 한번 하시죠~~~

자. 이렇게 작성을 해 보셨다면... 이제 실행을 멋드러지게 날려봅시다~~~ (저의 경운, 페이저 바의 텍스트 대신 이미지를 사용해서 더욱 아름답게 꾸며보았습니다. 이 방법은 PagerHelper 강좌에서 이미지 제공과 함께 방법을 알려드렸기에별도의 설명이 필요없을 것이라 믿어 의심치 않아 한답니다 ^^)

오홋홋~~ 잘 동작하지요???

물론, 테스트를 하다보면, 본문을 읽고 목록으로 올 경우 저절로 첫번째 페이지로 이동한다던가, 글을 수정하고 났더니 첫 번째 페이지로 이동한다던가 하는 문제가남아있긴 합니다. 그 외에도 몇가지 문제(?)가 사실 존재하고 있는 편이지요 ^^. 하지만, 여하튼 계층형 출력과 페이징까지는 끝낸 것 아니겠습니까??? 핫핫핫...

자잘한 여러가지 문제점들은 다음 시간에 바로잡아 보도록 하겠습니다. 그리고, 이제 검색으로 들어가 보도록 하겠습니다. 검색 부분은 성능까지 고려한다면상당히 심각하게 고민해야 하는 부분이기는 합니다만... 강좌에서는 단순 검색으로 이용해서 가볍게만 작성해 볼까 하고 있습니다.

물론, 그 사이에 지용군(www.mssql.org 운영자)님이 좋은 방안을 찾아주신다면 혹시 모르겠습니다만.... (어이~~ 지용군. 이젠 빼도 박도 못하게 되었어!! 음핫핫 !!!!)

그럼 다음 시간에 뵈요~~

PS : 혹시 기능적으로 추가되었으면 좋겠다는 것이 있다면...  게시판으로 의견 주세요 ^^


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})