DataList 또는 반복기 컨트롤에서 데이터 정렬(VB)

작성자 : Scott Mitchell

PDF 다운로드

이 자습서에서는 DataList 및 Repeater에 정렬 지원을 포함하는 방법과 데이터를 페이징하고 정렬할 수 있는 DataList 또는 Repeater를 구성하는 방법을 살펴봅합니다.

소개

이전 자습서에서는 DataList에 페이징 지원을 추가하는 방법을 검토했습니다. 개체를 반환하는 클래스(GetProductsAsPagedDataSource)에서 ProductsBLL 새 메서드를 PagedDataSource 만들었습니다. DataList 또는 Repeater에 바인딩되면 DataList 또는 Repeater는 요청된 데이터 페이지만 표시합니다. 이 기술은 GridView, DetailsView 및 FormView 컨트롤이 기본 제공 기본 페이징 기능을 제공하기 위해 내부적으로 사용하는 것과 유사합니다.

페이징 지원을 제공하는 것 외에도 GridView에는 기본 정렬 지원도 포함됩니다. DataList와 Repeater 모두 기본 제공 정렬 기능을 제공하지 않습니다. 그러나 정렬 기능은 약간의 코드로 추가할 수 있습니다. 이 자습서에서는 DataList 및 Repeater에 정렬 지원을 포함하는 방법과 데이터를 페이징하고 정렬할 수 있는 DataList 또는 Repeater를 구성하는 방법을 살펴봅합니다.

정렬 검토

보고서 데이터 페이징 및 정렬 자습서에서 보았듯이 GridView 컨트롤은 기본 정렬 지원을 제공합니다. 각 GridView 필드에는 데이터를 정렬할 데이터 필드를 나타내는 연결된 SortExpression가 있을 수 있습니다. GridView의 AllowSorting 속성이 로 설정된 true경우 속성 값이 있는 SortExpression 각 GridView 필드에는 해당 헤더가 LinkButton으로 렌더링됩니다. 사용자가 특정 GridView 필드의 헤더를 클릭하면 포스트백이 발생하고 데이터가 클릭한 필드의 SortExpression에 따라 정렬됩니다.

GridView 컨트롤에는 SortExpression 데이터가 정렬된 GridView 필드의 도 저장하는 SortExpression 속성이 있습니다. 또한 속성은 SortDirection 데이터를 오름차순 또는 내림차순으로 정렬할지 여부를 나타냅니다(사용자가 특정 GridView 필드의 헤더 링크를 연속해서 두 번 클릭하면 정렬 순서가 전환됨).

GridView가 데이터 원본 제어에 바인딩되면 해당 및 SortDirection 속성을 데이터 원본 제어에 적용 SortExpression 합니다. 데이터 소스 컨트롤은 데이터를 검색한 다음 제공된 SortExpressionSortDirection 속성에 따라 정렬합니다. 데이터를 정렬한 후 데이터 원본 컨트롤은 이를 GridView로 반환합니다.

DataList 또는 Repeater 컨트롤을 사용하여 이 기능을 복제하려면 다음을 수행해야 합니다.

  • 정렬 인터페이스 만들기
  • 정렬할 데이터 필드와 오름차순 또는 내림차순으로 정렬할지를 기억합니다.
  • ObjectDataSource에 특정 데이터 필드를 기준으로 데이터를 정렬하도록 지시합니다.

3단계와 4단계에서 이 세 가지 작업을 다룰 것입니다. 그런 다음 DataList 또는 Repeater에 페이징 및 정렬 지원을 모두 포함하는 방법을 살펴보겠습니다.

2단계: 반복기에서 제품 표시

정렬 관련 기능을 구현하는 것에 대해 걱정하기 전에 먼저 리피터 컨트롤에 제품을 나열해 보겠습니다. 먼저 폴더에서 Sorting.aspxPagingSortingDataListRepeater 페이지를 엽니다. 웹 페이지에 Repeater 컨트롤을 추가하고 해당 ID 속성을 로 SortableProducts설정합니다. Repeater의 스마트 태그에서 라는 ProductsDataSource 새 ObjectDataSource를 만들고 클래스의 GetProducts() 메서드에서 ProductsBLL 데이터를 검색하도록 구성합니다. INSERT, UPDATE 및 DELETE 탭의 드롭다운 목록에서 (없음) 옵션을 선택합니다.

ObjectDataSource를 만들고 GetProductsAsPagedDataSource() 메서드를 사용하도록 구성

그림 1: ObjectDataSource 만들기 및 메서드를 사용하도록 GetProductsAsPagedDataSource() 구성(전체 크기 이미지를 보려면 클릭)

UPDATE, INSERT 및 DELETE 탭의 Drop-Down Lists (없음)으로 설정합니다.

그림 2: UPDATE, INSERT 및 DELETE 탭의 Drop-Down Lists (없음)으로 설정합니다(전체 크기 이미지를 보려면 클릭).

DataList와 달리 Visual Studio는 데이터 원본에 바인딩한 ItemTemplate 후 Repeater 컨트롤에 대한 을 자동으로 만들지 않습니다. 또한 Repeater 컨트롤의 스마트 태그에 DataList에 있는 템플릿 편집 옵션이 없기 때문에 이를 ItemTemplate 선언적으로 추가해야 합니다. 제품의 이름, 공급자 및 범주를 표시한 이전 자습서와 동일한 ItemTemplate 를 사용하겠습니다.

를 추가한 ItemTemplate후 Repeater 및 ObjectDataSource의 선언적 태그는 다음과 유사하게 표시됩니다.

<asp:Repeater ID="SortableProducts" DataSourceID="ProductsDataSource"
    EnableViewState="False" runat="server">
    <ItemTemplate>
        <h4><asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:Label></h4>
        Category:
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'></asp:Label><br />
        Supplier:
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'></asp:Label><br />
        <br />
        <br />
    </ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProducts">
</asp:ObjectDataSource>

그림 3은 브라우저를 통해 볼 때 이 페이지를 보여줍니다.

각 제품의 이름, 공급자 및 범주가 표시됩니다.

그림 3: 각 제품의 이름, 공급자 및 범주가 표시됩니다(전체 크기 이미지를 보려면 클릭).

3단계: ObjectDataSource에 데이터 정렬 지시

Repeater에 표시된 데이터를 정렬하려면 ObjectDataSource에 데이터를 정렬할 정렬 식에 대해 알려야 합니다. ObjectDataSource는 데이터를 검색하기 전에 먼저 이벤트를 실행Selecting하여 정렬 식을 지정할 수 있는 기회를 제공합니다. Selecting 이벤트 처리기는 형식의 라는 속성 Arguments 이 있는 형식ObjectDataSourceSelectingEventArgsDataSourceSelectArguments의 개체를 전달합니다. 클래스는 DataSourceSelectArguments 데이터 소비자의 데이터 관련 요청을 데이터 소스 제어로 전달하도록 설계되었으며 속성을 포함합니다SortExpression.

ASP.NET 페이지에서 ObjectDataSource로 정렬 정보를 전달하려면 이벤트에 대한 Selecting 이벤트 처리기를 만들고 다음 코드를 사용합니다.

Protected Sub ProductsDataSource_Selecting(ByVal sender As Object, _
    ByVal e As ObjectDataSourceSelectingEventArgs) _
    Handles ProductsDataSource.Selecting
    e.Arguments.SortExpression = sortExpression
End Sub

sortExpression 값에는 데이터를 정렬할 데이터 필드의 이름(예: ProductName)이 할당되어야 합니다. 정렬 방향 관련 속성이 없으므로 데이터를 내림차순으로 정렬하려면 문자열 DESC를 sortExpression 값(예: ProductName DESC)에 추가합니다.

계속해서 sortExpression 에 대해 다른 하드 코딩된 값을 시도하고 브라우저에서 결과를 테스트합니다. 그림 4에서 보여 주듯이 ProductName DESC를 sortExpression으로 사용하는 경우 제품은 이름을 기준으로 사전순으로 정렬됩니다.

제품은 이름을 기준으로 사전순으로 정렬됩니다.

그림 4: 제품이 이름을 기준으로 사전순으로 정렬됩니다(전체 크기 이미지를 보려면 클릭).

4단계: 정렬 인터페이스 만들기 및 정렬 식 및 방향 기억

GridView에서 정렬 지원을 켜면 정렬 가능한 각 필드의 머리글 텍스트가 LinkButton으로 변환되어 클릭할 때 그에 따라 데이터를 정렬합니다. 이러한 정렬 인터페이스는 데이터가 열에 깔끔하게 배치되는 GridView에 적합합니다. 그러나 DataList 및 Repeater 컨트롤의 경우 다른 정렬 인터페이스가 필요합니다. 데이터 그리드가 아닌 데이터 목록에 대한 일반적인 정렬 인터페이스는 데이터를 정렬할 수 있는 필드를 제공하는 드롭다운 목록입니다. 이 자습서에 대한 이러한 인터페이스를 구현해 보겠습니다.

Repeater 위에 DropDownList 웹 컨트롤을 SortableProducts 추가하고 해당 ID 속성을 로 SortBy설정합니다. 속성 창 속성의 줄임표를 Items 클릭하여 ListItem 컬렉션 편집기 표시합니다. 를 추가하여 ListItem , CategoryNameSupplierName 필드를 기준으로 ProductName데이터를 정렬합니다. 또한 을 ListItem 추가하여 이름을 기준으로 제품을 사전순으로 정렬합니다.

속성은 ListItemText 모든 값(예: Name)으로 설정할 수 있지만 속성은 Value 데이터 필드의 이름(예: ProductName)으로 설정해야 합니다. 결과를 내림차순으로 정렬하려면 ProductName DESC 와 같은 데이터 필드 이름에 DESC 문자열을 추가합니다.

정렬 가능한 각 데이터 필드에 대한 ListItem 추가

그림 5: 정렬 가능한 각 데이터 필드에 대한 을 추가 ListItem 합니다.

마지막으로 DropDownList 오른쪽에 단추 웹 컨트롤을 추가합니다. 및 해당 IDRefreshRepeaterText 속성을 새로 고침으로 설정합니다.

ListItem 만들고 새로 고침 단추를 추가한 후 DropDownList 및 Button의 선언적 구문은 다음과 유사하게 표시됩니다.

<asp:DropDownList ID="SortBy" runat="server">
    <asp:ListItem Value="ProductName">Name</asp:ListItem>
    <asp:ListItem Value="ProductName DESC">Name (Reverse Order)
        </asp:ListItem>
    <asp:ListItem Value="CategoryName">Category</asp:ListItem>
    <asp:ListItem Value="SupplierName">Supplier</asp:ListItem>
</asp:DropDownList>
<asp:Button runat="server" ID="RefreshRepeater" Text="Refresh" />

정렬 DropDownList가 완료되면 다음에는 하드 코딩된 정렬 식이 아닌 선택한 SortBy``ListItem 의 속성을 사용하도록 ObjectDataSource의 SelectingValue 이벤트 처리기를 업데이트해야 합니다.

Protected Sub ProductsDataSource_Selecting _
    (ByVal sender As Object, ByVal e As ObjectDataSourceSelectingEventArgs) _
    Handles ProductsDataSource.Selecting
    ' Have the ObjectDataSource sort the results by the
    ' selected sort expression
    e.Arguments.SortExpression = SortBy.SelectedValue
End Sub

이 시점에서 페이지를 처음 방문할 때 제품은 기본적으로 선택된 대로 데이터 필드를 SortByListItem 기준으로 ProductName 정렬됩니다(그림 6 참조). 범주와 같은 다른 정렬 옵션을 선택하고 새로 고침을 클릭하면 그림 7과 같이 포스트백이 발생하고 범주 이름으로 데이터를 다시 정렬합니다.

제품은 처음에 이름을 기준으로 정렬됩니다.

그림 6: 제품이 처음에 이름별로 정렬됨(전체 크기 이미지를 보려면 클릭)

이제 제품이 범주별로 정렬됩니다.

그림 7: 이제 제품이 범주별로 정렬됨(전체 크기 이미지를 보려면 클릭)

참고

새로 고침 단추를 클릭하면 Repeater의 뷰 상태가 비활성화되어 리피터가 모든 포스트백의 데이터 원본에 다시 바인딩되므로 데이터가 자동으로 다시 정렬됩니다. 반복기 보기 상태를 사용하도록 설정한 경우 정렬 드롭다운 목록을 변경해도 정렬 순서에 영향을 주지 않습니다. 이 문제를 해결하려면 Refresh Button 이벤트에 대한 이벤트 처리기를 만들고 Repeater의 ClickDataBind() 메서드를 호출하여 리피터를 데이터 원본에 다시 바인딩합니다.

정렬 식 및 방향 기억

정렬할 수 없는 관련 포스트백이 발생할 수 있는 페이지에서 정렬 가능한 DataList 또는 Repeater를 만들 때는 정렬 식과 방향을 포스트백 간에 기억해야 합니다. 예를 들어 이 자습서에서 리피터를 업데이트하여 각 제품에 삭제 단추를 포함하도록 했습니다. 사용자가 삭제 단추를 클릭하면 일부 코드를 실행하여 선택한 제품을 삭제한 다음 데이터를 리피터에 다시 바인딩합니다. 정렬 세부 정보가 포스트백 간에 유지되지 않으면 화면에 표시되는 데이터가 원래 정렬 순서로 되돌리기.

이 자습서의 경우 DropDownList는 정렬 식과 방향을 뷰 상태에 암시적으로 저장합니다. 다양한 정렬 옵션을 제공하는 LinkButtons와 함께 다른 정렬 인터페이스를 사용하는 경우 포스트백에서 정렬 순서를 기억하기 위해 주의해야 합니다. 이는 정렬 매개 변수를 쿼리 문자열에 포함하거나 다른 상태 지속성 기술을 통해 정렬 매개 변수를 페이지 뷰 상태에 저장하여 수행할 수 있습니다.

이 자습서의 향후 예제에서는 페이지 보기 상태에서 정렬 세부 정보를 유지하는 방법을 살펴봅니다.

5단계: 기본 페이징을 사용하는 DataList에 정렬 지원 추가

이전 자습서에서는 DataList를 사용하여 기본 페이징을 구현하는 방법을 검토했습니다. 페이징된 데이터를 정렬하는 기능을 포함하도록 이 이전 예제를 확장해 보겠습니다. 먼저 폴더에서 SortingWithDefaultPaging.aspxPaging.aspx 페이지를 PagingSortingDataListRepeater 엽니다. Paging.aspx 페이지에서 원본 단추를 클릭하여 페이지의 선언적 태그를 봅니다. 선택한 텍스트를 복사하여(그림 8 참조) 태그 사이의 선언적 태그 SortingWithDefaultPaging.aspx<asp:Content> 붙여넣습니다.

asp:Content> 태그의 <선언적 태그를 Paging.aspx SortingWithDefaultPaging.aspx

그림 8: 태그의 <asp:Content> 선언적 태그를 에서 Paging.aspxSortingWithDefaultPaging.aspx 로 복제(전체 크기 이미지를 보려면 클릭)

선언적 태그를 복사한 후 페이지의 코드 숨김 클래스에 있는 Paging.aspx 메서드 및 속성을 의 코드 숨김 클래스에 복사합니다 SortingWithDefaultPaging.aspx. 그런 다음 잠시 시간을 내어 브라우저에서 페이지를 봅니 SortingWithDefaultPaging.aspx 다. 와 동일한 기능과 모양을 Paging.aspx표시해야 합니다.

기본 페이징 및 정렬 방법을 포함하도록 ProductsBLL 향상

이전 자습서에서는 클래스에서 개체를 GetProductsAsPagedDataSource(pageIndex, pageSize)ProductsBLL 반환하는 메서드를 PagedDataSource 만들었습니다. 이 PagedDataSource 개체는 BLL GetProducts() 메서드를 통해 모든 제품으로 채워졌지만 DataList에 바인딩된 경우 지정된 pageIndexpageSize 입력 매개 변수에 해당하는 레코드만 표시되었습니다.

이 자습서의 앞부분에서는 ObjectDataSource의 Selecting 이벤트 처리기에서 정렬 식을 지정하여 정렬 지원을 추가했습니다. 이는 ObjectDataSource가 메서드에서 반환된 것과 같이 정렬할 수 있는 개체를 ProductsDataTable 반환 GetProducts() 할 때 잘 작동합니다. 그러나 메서드에서 반환된 PagedDataSource 개체는 GetProductsAsPagedDataSource 내부 데이터 원본의 정렬을 지원하지 않습니다. 대신 에 배치하기 전에 메서드에서 반환된 GetProducts() 결과를 정렬해야 합니다PagedDataSource.

이렇게 하려면 클래스GetProductsSortedAsPagedDataSource(sortExpression, pageIndex, pageSize)에 새 메서드를 ProductsBLL 만듭니다. 메서드에서 반환된 ProductsDataTableGetProducts() 정렬하려면 기본 의 DataTableView속성을 지정 Sort 합니다.

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductsSortedAsPagedDataSource _
    (sortExpression As String, pageIndex As Integer, pageSize As Integer) _
    As PagedDataSource
    ' Get ALL of the products
    Dim products As Northwind.ProductsDataTable = GetProducts()
    'Sort the products
    products.DefaultView.Sort = sortExpression
    ' Limit the results through a PagedDataSource
    Dim pagedData As New PagedDataSource()
    pagedData.DataSource = products.DefaultView
    pagedData.AllowPaging = True
    pagedData.CurrentPageIndex = pageIndex
    pagedData.PageSize = pageSize
    Return pagedData
End Function

메서드는 GetProductsSortedAsPagedDataSource 이전 자습서에서 만든 메서드와 GetProductsAsPagedDataSource 약간 다릅니다. 특히 는 GetProductsSortedAsPagedDataSource 추가 입력 매개 변수 sortExpression 를 수락하고 이 값을 SortDefaultView속성에 ProductDataTable 할당합니다. 몇 줄의 코드가 나중에 PagedDataSource 개체의 DataSource에 ProductDataTableDefaultView할당됩니다.

GetProductsSortedAsPagedDataSource 메서드 호출 및 SortExpression 입력 매개 변수 값 지정

메서드가 GetProductsSortedAsPagedDataSource 완료되면 다음 단계는 이 매개 변수의 값을 제공하는 것입니다. 의 SortingWithDefaultPaging.aspx ObjectDataSource는 현재 메서드를 호출 GetProductsAsPagedDataSource 하도록 구성되어 있으며 컬렉션에 지정된 두 개의 를 통해 두 QueryStringParameters입력 매개 변수를 SelectParameters 전달합니다. 이 두 QueryStringParameters 가지는 메서드의 pageIndexpageSize 매개 변수의 원본 GetProductsAsPagedDataSource 이 쿼리 문자열 필드 pageIndexpageSize에서 온 것임을 나타냅니다.

GetProductsSortedAsPagedDataSource 메서드를 호출할 수 있도록 ObjectDataSource의 SelectMethod 속성을 업데이트합니다. 그런 다음, querystring 필드 sortExpression에서 sortExpression 입력 매개 변수에 액세스할 수 있도록 새 QueryStringParameter 를 추가합니다. 를 QueryStringParameterDefaultValue ProductName 로 설정합니다.

이러한 변경 후 ObjectDataSource의 선언적 태그는 다음과 같이 표시됩니다.

<asp:ObjectDataSource ID="ProductsDefaultPagingDataSource"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsSortedAsPagedDataSource"
    OnSelected="ProductsDefaultPagingDataSource_Selected" runat="server">
    <SelectParameters>
        <asp:QueryStringParameter DefaultValue="ProductName"
            Name="sortExpression" QueryStringField="sortExpression"
            Type="String" />
        <asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
            QueryStringField="pageIndex" Type="Int32" />
        <asp:QueryStringParameter DefaultValue="4" Name="pageSize"
            QueryStringField="pageSize" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

이 시점에서 SortingWithDefaultPaging.aspx 페이지는 제품 이름으로 결과를 사전순으로 정렬합니다(그림 9 참조). 이는 기본적으로 ProductName 값이 메서드의 sortExpression 매개 변수로 GetProductsSortedAsPagedDataSource 전달되기 때문입니다.

기본적으로 결과는 ProductName별로 정렬됩니다.

그림 9: 기본적으로 결과는 정렬 기준 ProductName 입니다(전체 크기 이미지를 보려면 클릭).

쿼리 문자열 필드를 수동으로 추가 sortExpression 하면 결과와 같은 SortingWithDefaultPaging.aspx?sortExpression=CategoryName 쿼리 문자열 필드가 지정된 sortExpression에 의해 정렬됩니다. 그러나 이 sortExpression 매개 변수는 다른 데이터 페이지로 이동할 때 쿼리 문자열에 포함되지 않습니다. 실제로 다음 또는 마지막 페이지 단추를 클릭하면 다시 Paging.aspx! 또한 현재 정렬 인터페이스가 없습니다. 사용자가 페이징된 데이터의 정렬 순서를 변경할 수 있는 유일한 방법은 쿼리 문자열을 직접 조작하는 것입니다.

정렬 인터페이스 만들기

먼저 사용자를 SortingWithDefaultPaging.aspx (대신Paging.aspx)로 보내고 쿼리 문자열에 값을 포함 sortExpression 하도록 메서드를 업데이트 RedirectUser 해야 합니다. 읽기 전용인 페이지 수준 명명 SortExpression 된 속성도 추가해야 합니다. 이 속성은 이전 자습서에서 만든 및 속성과 PageSize 유사하게 PageIndex 쿼리 문자열 필드의 sortExpression 값(있는 경우)을 반환하고, 그렇지 않으면 기본값(ProductName)을 반환합니다.

현재 메서드는 RedirectUser 표시할 페이지의 인덱스에 대한 단일 입력 매개 변수만 허용합니다. 그러나 쿼리 문자열에 지정된 항목이 아닌 정렬 식을 사용하여 사용자를 데이터의 특정 페이지로 리디렉션하려는 경우가 있을 수 있습니다. 잠시 후에 이 페이지에 대한 정렬 인터페이스를 만듭니다. 여기에는 지정된 열별로 데이터를 정렬하기 위한 일련의 Button Web 컨트롤이 포함됩니다. 이러한 단추 중 하나를 클릭하면 적절한 정렬 식 값을 전달하는 사용자를 리디렉션하려고 합니다. 이 기능을 제공하려면 두 가지 버전의 메서드를 만듭니다 RedirectUser . 첫 번째 인덱스는 표시할 페이지 인덱스만 허용하고 두 번째 인덱스는 페이지 인덱스 및 정렬 식을 수락해야 합니다.

Private ReadOnly Property SortExpression() As String
    Get
        If Not String.IsNullOrEmpty(Request.QueryString("sortExpression")) Then
            Return Request.QueryString("sortExpression")
        Else
            Return "ProductName"
        End If
    End Get
End Property
Private Sub RedirectUser(ByVal sendUserToPageIndex As Integer)
    ' Use the SortExpression property to get the sort expression
    ' from the querystring
    RedirectUser(sendUserToPageIndex, SortExpression)
End Sub
Private Sub RedirectUser(ByVal sendUserToPageIndex As Integer,
    ByVal sendUserSortingBy As String)
    ' Send the user to the requested page with the
    ' requested sort expression
    Response.Redirect(String.Format("SortingWithDefaultPaging.aspx?" & _
        "pageIndex={0}&pageSize={1}&sortExpression={2}", _
        sendUserToPageIndex, PageSize, sendUserSortingBy))
End Sub

이 자습서의 첫 번째 예제에서는 DropDownList를 사용하여 정렬 인터페이스를 만들었습니다. 이 예제에서는 DataList 위에 배치된 단추 웹 컨트롤 3개를 사용하여 정렬을 ProductName위해 1개, 에 하나씩 CategoryName, 에 대해 SupplierName하나씩 사용합니다. 세 개의 Button Web 컨트롤을 추가하여 및 IDText 속성을 적절하게 설정합니다.

<p>
    <asp:Button runat="server" id="SortByProductName"
        Text="Sort by Product Name" />
    <asp:Button runat="server" id="SortByCategoryName"
        Text="Sort by Category" />
    <asp:Button runat="server" id="SortBySupplierName"
        Text="Sort by Supplier" />
</p>

다음으로 각각에 Click 대한 이벤트 처리기를 만듭니다. 이벤트 처리기는 메서드를 RedirectUser 호출하여 적절한 정렬 식을 사용하여 사용자를 첫 번째 페이지로 반환해야 합니다.

Protected Sub SortByProductName_Click(sender As Object, e As EventArgs) _
    Handles SortByProductName.Click
    'Sort by ProductName
    RedirectUser(0, "ProductName")
End Sub
Protected Sub SortByCategoryName_Click(sender As Object, e As EventArgs) _
    Handles SortByCategoryName.Click
    'Sort by CategoryName
    RedirectUser(0, "CategoryName")
End Sub
Protected Sub SortBySupplierName_Click(sender As Object, e As EventArgs) _
    Handles SortBySupplierName.Click
    'Sort by SupplierName
    RedirectUser(0, "SupplierName")
End Sub

페이지를 처음 방문할 때 데이터는 제품 이름을 기준으로 사전순으로 정렬됩니다(그림 9 참조). 다음 단추를 클릭하여 데이터의 두 번째 페이지로 이동한 다음 범주별 정렬 단추를 클릭합니다. 그러면 범주 이름으로 정렬된 데이터의 첫 번째 페이지로 돌아갑니다(그림 10 참조). 마찬가지로 공급자별 정렬 단추를 클릭하면 데이터의 첫 번째 페이지에서 시작하여 공급자별로 데이터를 정렬합니다. 정렬 선택은 데이터가 페이징될 때 기억됩니다. 그림 11은 범주별로 정렬한 다음 데이터의 13번째 페이지로 이동한 후의 페이지를 보여줍니다.

제품은 범주별로 정렬됩니다.

그림 10: 제품이 범주별로 정렬됨(전체 크기 이미지를 보려면 클릭)

정렬 식은 데이터를 페이징할 때 기억됩니다.

그림 11: 정렬 식은 데이터를 페이징할 때 기억됩니다(전체 크기 이미지를 보려면 클릭).

6단계: 반복기에서 레코드를 통한 사용자 지정 페이징

DataList 예제는 비효율적인 기본 페이징 기술을 사용하여 데이터를 통해 5단계 페이지에서 검사했습니다. 충분히 많은 양의 데이터를 페이징하는 경우 사용자 지정 페이징을 사용해야 합니다. 대량의 데이터를 효율적으로 페이징하고 사용자 지정 페이징 데이터 정렬 자습서로 돌아가서 사용자 지정 페이징 및 사용자 지정 페이징 데이터 정렬을 활용하기 위해 BLL에서 기본 페이징과 사용자 지정 페이징 및 만든 메서드의 차이점을 조사했습니다. 특히 이전 두 자습서에서는 클래스에 다음 세 가지 메서드를 추가했습니다 ProductsBLL .

  • GetProductsPaged(startRowIndex, maximumRows)startRowIndex 에서 시작하여 maximumRows를 초과하지 않는 레코드의 특정 하위 집합을 반환합니다.
  • GetProductsPagedAndSorted(sortExpression, startRowIndex, maximumRows) 는 지정된 sortExpression 입력 매개 변수를 기준으로 정렬된 레코드의 특정 하위 집합을 반환합니다.
  • TotalNumberOfProducts() 는 데이터베이스 테이블의 총 레코드 Products 수를 제공합니다.

이러한 메서드를 사용하여 DataList 또는 Repeater 컨트롤을 사용하여 데이터를 효율적으로 페이저닝하고 정렬할 수 있습니다. 이를 설명하기 위해 먼저 사용자 지정 페이징 지원을 사용하여 Repeater 컨트롤을 만들어 보겠습니다. 그런 다음 정렬 기능을 추가합니다.

폴더에서 SortingWithCustomPaging.aspxPagingSortingDataListRepeater 페이지를 열고 페이지에 반복기를 추가하여 속성을 IDProducts로 설정합니다. Repeater의 스마트 태그에서 라는 ProductsDataSource새 ObjectDataSource를 만듭니다. 클래스의 GetProductsPaged 메서드에서 ProductsBLL 해당 데이터를 선택하도록 구성합니다.

ProductsBLL 클래스의 GetProductsPaged 메서드를 사용하도록 ObjectDataSource 구성

그림 12: 클래스의 GetProductsPaged 메서드를 사용하도록 ProductsBLL ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)

UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정한 다음 다음 단추를 클릭합니다. 이제 데이터 원본 구성 마법사에서 메서드 startRowIndex 및 maximumRows 입력 매개 변수의 원본 GetProductsPaged 을 묻는 메시지를 표시합니다. 실제로 이러한 입력 매개 변수는 무시됩니다. 대신 startRowIndexmaximumRows 값은 이 자습서의 첫 번째 데모에서 sortExpression을 지정한 방법과 마찬가지로 ObjectDataSource 이벤트 Selecting 처리기의 속성을 통해 Arguments 전달됩니다. 따라서 매개 변수 원본 드롭다운 목록은 없음 로 설정된 마법사에 그대로 둡니다.

매개 변수 원본을 없음으로 설정

그림 13: 매개 변수 원본을 없음으로 설정된 상태로 둡니다(전체 크기 이미지를 보려면 클릭).

참고

ObjectDataSource의 EnablePaging 속성을 true로 설정하지 마세요. 이로 인해 ObjectDataSource는 자체 startRowIndexmaximumRows 매개 변수를 SelectMethod 기존 매개 변수 목록에 자동으로 포함합니다. 속성은 EnablePaging 사용자 지정 페이징된 데이터를 GridView, DetailsView 또는 FormView 컨트롤에 바인딩할 때 유용합니다. 이러한 컨트롤은 속성이 일 때만 사용할 수 있는 EnablePaging ObjectDataSource의 특정 동작을 예상하기 때문입니다 true. DataList 및 Repeater에 대한 페이징 지원을 수동으로 추가해야 하므로 ASP.NET 페이지 내에서 직접 필요한 기능을 사용할 수 있으므로 이 속성을 (기본값)으로 설정합니다 false .

마지막으로 제품의 이름, 범주 및 공급자가 표시되도록 Repeater ItemTemplate 를 정의합니다. 이러한 변경 후 Repeater 및 ObjectDataSource의 선언적 구문은 다음과 유사하게 표시됩니다.

<asp:Repeater ID="Products" runat="server" DataSourceID="ProductsDataSource"
    EnableViewState="False">
    <ItemTemplate>
        <h4><asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:Label></h4>
        Category:
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'></asp:Label><br />
        Supplier:
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'></asp:Label><br />
        <br />
        <br />
    </ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsPaged" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

잠시 브라우저를 통해 페이지를 방문하여 레코드가 반환되지 않습니다. startRowIndex 및 maximumRows 매개 변수 값을 아직 지정하지 않았기 때문입니다. 따라서 0의 값은 둘 다에 대해 전달됩니다. 이러한 값을 지정하려면 ObjectDataSource 이벤트에 Selecting 대한 이벤트 처리기를 만들고 이러한 매개 변수 값을 프로그래밍 방식으로 하드 코딩된 값 0과 5로 각각 설정합니다.

Protected Sub ProductsDataSource_Selecting(sender As Object, _
    e As ObjectDataSourceSelectingEventArgs) _
    Handles ProductsDataSource.Selecting
    e.InputParameters("startRowIndex") = 0
    e.InputParameters("maximumRows") = 5
End Sub

이 변경 내용으로 브라우저를 통해 볼 때 페이지에 처음 5개의 제품이 표시됩니다.

처음 다섯 개의 레코드가 표시됩니다.

그림 14: 처음 다섯 개의 레코드가 표시됩니다(전체 크기 이미지를 보려면 클릭).

참고

그림 14에 나열된 제품은 효율적인 사용자 지정 페이징 쿼리를 수행하는 저장 프로시저가 결과를 ProductName로 정렬하기 때문에 GetProductsPaged 제품 이름으로 정렬됩니다.

사용자가 페이지를 단계별로 실행할 수 있도록 하려면 시작 행 인덱스와 최대 행을 추적하고 포스트백에서 이러한 값을 기억해야 합니다. 기본 페이징 예제에서는 쿼리 문자열 필드를 사용하여 이러한 값을 유지했습니다. 이 데모의 경우 이 정보를 페이지의 보기 상태로 유지해 보겠습니다. 다음 두 가지 속성을 만듭니다.

Private Property StartRowIndex() As Integer
    Get
        Dim o As Object = ViewState("StartRowIndex")
        If o Is Nothing Then
            Return 0
        Else
            Return CType(o, Integer)
        End If
    End Get
    Set(ByVal value As Integer)
        ViewState("StartRowIndex") = value
    End Set
End Property
Private Property MaximumRows() As Integer
    Get
        Dim o As Object = ViewState("MaximumRows")
        If o Is Nothing Then
            Return 5
        Else
            Return CType(o, Integer)
        End If
    End Get
    Set(ByVal value As Integer)
        ViewState("MaximumRows") = value
    End Set
End Property

다음으로, 하드 코딩된 값 0과 5 대신 및 MaximumRows 속성을 사용할 StartRowIndex 수 있도록 Selecting 이벤트 처리기에서 코드를 업데이트합니다.

e.InputParameters("startRowIndex") = 0
e.InputParameters("maximumRows") = 5

이 시점에서 페이지에는 처음 5개의 레코드만 표시됩니다. 그러나 이러한 속성이 준비되면 페이징 인터페이스를 만들 준비가 된 것입니다.

페이징 인터페이스 추가

표시되는 데이터의 페이지와 총 페이지 수를 표시하는 레이블 웹 컨트롤을 포함하여 기본 페이징 예제에서 사용되는 동일한 First, Previous, Next, Last 페이징 인터페이스를 사용하겠습니다. 4개의 단추 웹 컨트롤과 레이블을 반복기 아래에 추가합니다.

<p>
    <asp:Button runat="server" ID="FirstPage" Text="<< First" />
    <asp:Button runat="server" ID="PrevPage" Text="< Prev" />
    <asp:Button runat="server" ID="NextPage" Text="Next >" />
    <asp:Button runat="server" ID="LastPage" Text="Last >>" />
</p>
<p>
    <asp:Label runat="server" ID="CurrentPageNumber"></asp:Label>
</p>

다음으로, 4개의 단추에 대한 이벤트 처리기를 만듭니 Click 다. 이러한 단추 중 하나를 클릭하면 를 업데이트 StartRowIndex 하고 데이터를 반복기로 다시 바인딩해야 합니다. 첫 번째, 이전 및 다음 단추의 코드는 충분히 간단하지만 마지막 단추의 경우 데이터의 마지막 페이지에 대한 시작 행 인덱스를 어떻게 결정합니까? 이 인덱스를 계산하고 다음 및 마지막 단추를 사용하도록 설정해야 하는지 여부를 확인하려면 페이징되는 총 레코드 수를 알아야 합니다. 클래스의 TotalNumberOfProducts() 메서드를 ProductsBLL 호출하여 이를 확인할 수 있습니다. 메서드의 결과를 TotalNumberOfProducts() 반환하는 라는 TotalRowCount 읽기 전용 페이지 수준 속성을 만들어 보겠습니다.

Private ReadOnly Property TotalRowCount() As Integer
    Get
        'Return the value from the TotalNumberOfProducts() method
        Dim productsAPI As New ProductsBLL()
        Return productsAPI.TotalNumberOfProducts()
    End Get
End Property

이제 이 속성을 사용하여 마지막 페이지의 시작 행 인덱스 를 확인할 수 있습니다. 특히 , 을 곱MaximumRows한 1MaximumRows을 뺀 값의 TotalRowCount 정수 결과입니다. 이제 네 개의 페이징 인터페이스 단추에 대한 이벤트 처리기를 작성 Click 할 수 있습니다.

Protected Sub FirstPage_Click(sender As Object, e As EventArgs) _
    Handles FirstPage.Click
    'Return to StartRowIndex of 0 and rebind data
    StartRowIndex = 0
    Products.DataBind()
End Sub
Protected Sub PrevPage_Click(sender As Object, e As EventArgs) _
    Handles PrevPage.Click
    'Subtract MaximumRows from StartRowIndex and rebind data
    StartRowIndex -= MaximumRows
    Products.DataBind()
End Sub
Protected Sub NextPage_Click(sender As Object, e As EventArgs) _
    Handles NextPage.Click
    'Add MaximumRows to StartRowIndex and rebind data
    StartRowIndex += MaximumRows
    Products.DataBind()
End Sub
Protected Sub LastPage_Click(sender As Object, e As EventArgs) _
    Handles LastPage.Click
    'Set StartRowIndex = to last page's starting row index and rebind data
    StartRowIndex = ((TotalRowCount - 1) \ MaximumRows) * MaximumRows
    Products.DataBind()
End Sub

마지막으로, 마지막 페이지를 볼 때 데이터의 첫 번째 페이지와 다음 및 마지막 단추를 볼 때 페이징 인터페이스에서 첫 번째 및 이전 단추를 사용하지 않도록 설정해야 합니다. 이렇게 하려면 ObjectDataSource의 Selecting 이벤트 처리기에 다음 코드를 추가합니다.

' Disable the paging interface buttons, if needed
FirstPage.Enabled = StartRowIndex <> 0
PrevPage.Enabled = StartRowIndex <> 0
Dim LastPageStartRowIndex As Integer = _
    ((TotalRowCount - 1) \ MaximumRows) * MaximumRows
NextPage.Enabled = (StartRowIndex < LastPageStartRowIndex)
LastPage.Enabled = (StartRowIndex < LastPageStartRowIndex)

이러한 Click 이벤트 처리기와 코드를 추가하여 현재 시작 행 인덱스에 따라 페이징 인터페이스 요소를 사용하거나 사용하지 않도록 설정한 후 브라우저에서 페이지를 테스트합니다. 그림 15에서 알 수 있듯이 페이지를 처음 방문하면 첫 번째 및 이전 단추가 비활성화됩니다. 다음을 클릭하면 데이터의 두 번째 페이지가 표시되고 마지막을 클릭하면 최종 페이지가 표시됩니다(그림 16 및 17 참조). 데이터의 마지막 페이지를 볼 때 다음 단추와 마지막 단추가 모두 비활성화됩니다.

제품의 첫 페이지를 볼 때 이전 및 마지막 단추가 비활성화됨

그림 15: 제품의 첫 페이지를 볼 때 이전 및 마지막 단추가 비활성화됨(전체 크기 이미지를 보려면 클릭)

제품의 두 번째 페이지가 표시됩니다.

그림 16: 제품의 두 번째 페이지가 표시됩니다(전체 크기 이미지를 보려면 클릭).

마지막을 클릭하면 데이터의 마지막 페이지가 표시됩니다.

그림 17: 마지막을 클릭하면 데이터의 마지막 페이지가 표시됩니다(전체 크기 이미지를 보려면 클릭).

7단계: 사용자 지정 페이징 반복기를 사용하여 정렬 지원 포함

이제 사용자 지정 페이징이 구현되었으므로 정렬 지원을 포함할 준비가 되었습니다. ProductsBLL 클래스의 GetProductsPagedAndSorted 메서드는 startRowIndexmaximumRows 입력 매개 변수와 동일GetProductsPaged하지만 추가 sortExpression 입력 매개 변수를 허용합니다. 에서 SortingWithCustomPaging.aspx메서드를 GetProductsPagedAndSorted 사용하려면 다음 단계를 수행해야 합니다.

  1. ObjectDataSource의 SelectMethod 속성을 에서 로 GetProductsPagedGetProductsPagedAndSorted변경합니다.
  2. ObjectDataSource 컬렉션에 sortExpressionParameter 개체를 SelectParameters 추가합니다.
  3. 페이지 보기 상태를 통해 포스트백에서 해당 값을 유지하는 프라이빗 페이지 수준 SortExpression 속성을 만듭니다.
  4. ObjectDataSource의 Selecting 이벤트 처리기를 업데이트하여 ObjectDataSource의 sortExpression 매개 변수에 페이지 수준 SortExpression 속성의 값을 할당합니다.
  5. 정렬 인터페이스를 만듭니다.

먼저 ObjectDataSource의 SelectMethod 속성을 업데이트하고 sortExpression을 추가합니다Parameter. sortExpressionParameterType 속성이 로 설정되어 있는지 확인합니다String. 이러한 처음 두 작업을 완료한 후 ObjectDataSource의 선언적 태그는 다음과 같습니다.

<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsPagedAndSorted"
    OnSelecting="ProductsDataSource_Selecting">
    <SelectParameters>
        <asp:Parameter Name="sortExpression" Type="String" />
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

다음으로, 상태를 보기 위해 값이 직렬화된 페이지 수준 SortExpression 속성이 필요합니다. 정렬 식 값이 설정되지 않은 경우 ProductName을 기본값으로 사용합니다.

Private Property SortExpression() As String
    Get
        Dim o As Object = ViewState("SortExpression")
        If o Is Nothing Then
            Return "ProductName"
        Else
            Return o.ToString()
        End If
    End Get
    Set(ByVal value As String)
        ViewState("SortExpression") = value
    End Set
End Property

ObjectDataSource가 메서드를 GetProductsPagedAndSorted 호출하기 전에 sortExpressionParameter 을 속성 값 SortExpression 으로 설정해야 합니다. 이벤트 처리기 Selecting 에서 다음 코드 줄을 추가합니다.

e.InputParameters("sortExpression") = SortExpression

남은 것은 정렬 인터페이스를 구현하는 것입니다. 마지막 예제에서와 같이 사용자가 제품 이름, 범주 또는 공급자별로 결과를 정렬할 수 있는 세 가지 Button Web 컨트롤을 사용하여 정렬 인터페이스를 구현해 보겠습니다.

<asp:Button runat="server" id="SortByProductName"
    Text="Sort by Product Name" />
<asp:Button runat="server" id="SortByCategoryName"
    Text="Sort by Category" />
<asp:Button runat="server" id="SortBySupplierName"
    Text="Sort by Supplier" />

이러한 세 개의 단추 컨트롤에 대한 이벤트 처리기를 만듭니 Click 다. 이벤트 처리기에서 를 0으로 다시 설정하고 StartRowIndex , 를 적절한 값으로 설정하고 SortExpression , 데이터를 Repeater에 다시 바인딩합니다.

Protected Sub SortByProductName_Click(sender As Object, e As EventArgs) _
    Handles SortByProductName.Click
    StartRowIndex = 0
    SortExpression = "ProductName"
    Products.DataBind()
End Sub
Protected Sub SortByCategoryName_Click(sender As Object, e As EventArgs) _
    Handles SortByCategoryName.Click
    StartRowIndex = 0
    SortExpression = "CategoryName"
    Products.DataBind()
End Sub
Protected Sub SortBySupplierName_Click(sender As Object, e As EventArgs) _
    Handles SortBySupplierName.Click
    StartRowIndex = 0
    SortExpression = "CompanyName"
    Products.DataBind()
End Sub

그게 전부입니다! 사용자 지정 페이징 및 정렬을 구현하는 여러 단계가 있었지만 단계는 기본 페이징에 필요한 단계와 매우 유사했습니다. 그림 18에서는 범주별로 정렬할 때 데이터의 마지막 페이지를 볼 때의 제품을 보여 줍니다.

범주별로 정렬된 데이터의 마지막 페이지가 표시됩니다.

그림 18: 범주별로 정렬된 데이터의 마지막 페이지가 표시됩니다(전체 크기 이미지를 보려면 클릭).

참고

이전 예제에서는 공급자 SupplierName을 기준으로 정렬할 때 정렬 식으로 사용되었습니다. 그러나 사용자 지정 페이징 구현의 경우 CompanyName을 사용해야 합니다. 사용자 지정 페이징 GetProductsPagedAndSorted 구현을 담당하는 저장 프로시저가 정렬 식을 ROW_NUMBER() 키워드(keyword) ROW_NUMBER() 전달하기 때문에 키워드(keyword) 별칭이 아닌 실제 열 이름이 필요합니다. 따라서 정렬 식에 쿼리()에 Suppliers 사용되는 SELECT 별칭 대신 (SupplierName테이블의 열 이름)을 사용해야 CompanyName 합니다.

요약

DataList와 Repeater는 기본 제공 정렬 지원을 제공하지 않지만 약간의 코드와 사용자 지정 정렬 인터페이스를 사용하여 이러한 기능을 추가할 수 있습니다. 페이징이 아닌 정렬을 구현할 때 ObjectDataSource의 Select 메서드에 전달된 개체를 통해 DataSourceSelectArguments 정렬 식을 지정할 수 있습니다. 이 DataSourceSelectArguments 개체의 속성은 SortExpression ObjectDataSource의 Selecting 이벤트 처리기에 할당할 수 있습니다.

이미 페이징 지원을 제공하는 DataList 또는 Repeater에 정렬 기능을 추가하려면 정렬 식을 허용하는 메서드를 포함하도록 비즈니스 논리 계층을 사용자 지정하는 것이 가장 쉬운 방법입니다. 그런 다음 ObjectDataSource 의 SelectParameters매개 변수를 통해 이 정보를 전달할 수 있습니다.

이 자습서에서는 DataList 및 Repeater 컨트롤을 사용하여 페이징 및 정렬 검사를 완료합니다. 다음 및 마지막 자습서에서는 항목별로 사용자 시작 기능을 제공하기 위해 DataList 및 Repeater 템플릿에 단추 웹 컨트롤을 추가하는 방법을 살펴봅니다.

행복한 프로그래밍!

저자 정보

7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 자신을 가르친다 ASP.NET 2.0 24 시간. 그는 에서 찾을 수있는 그의 블로그를 통해 또는 에 mitchell@4GuysFromRolla.comhttp://ScottOnWriting.NET도달 할 수 있습니다.

특별 감사

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 David Suru였습니다. 예정된 MSDN 문서를 검토하시겠습니까? 그렇다면 에 줄을 놓습니다 mitchell@4GuysFromRolla.com.