다음을 통해 공유


세부 정보 DataList와 함께 마스터 레코드의 글머리 기호 목록을 사용하는 마스터/세부 정보(VB)

스콧 미첼

PDF 다운로드

이 자습서에서는 이전 자습서의 2페이지 마스터/세부 보고서를 단일 페이지로 압축하여 화면 왼쪽에 범주 이름의 글머리 기호 목록을 표시하고 화면 오른쪽에 선택한 범주의 제품을 보여 줍니다.

소개

이전 자습서에서는 두 페이지에 걸쳐 마스터/세부 보고서를 구분하는 방법을 살펴보았습니다. 마스터 페이지에서는 리피터 컨트롤을 사용하여 범주의 글머리 기호 목록을 렌더링했습니다. 각 범주 이름은 클릭할 때 사용자를 세부 정보 페이지로 데려가는 하이퍼링크였으며, 여기서 두 열의 DataList는 선택한 범주에 속하는 제품을 보여 줍니다.

이 자습서에서는 두 페이지 자습서를 단일 페이지로 압축하여 화면 왼쪽에 각 범주 이름이 LinkButton으로 렌더링된 범주 이름의 글머리 기호 목록을 표시합니다. 범주 이름 LinkButtons 중 하나를 클릭하면 포스트백이 유도되고 선택한 범주의 제품을 화면 오른쪽의 두 열 DataList에 바인딩합니다. 왼쪽의 리피터는 각 범주의 이름을 표시하는 것 외에도 지정된 범주에 대한 총 제품 수를 보여 줍니다(그림 1 참조).

범주 이름 및 총 제품 수가 왼쪽에 표시됩니다.

그림 1: 범주 이름 및 총 제품 수가 왼쪽에 표시됩니다(전체 크기 이미지를 보려면 클릭).

1단계: 화면 왼쪽 부분에 리피터 표시

이 자습서에서는 선택한 범주 제품의 왼쪽에 범주의 글머리 기호 목록을 표시해야 합니다. 웹 페이지 내의 콘텐츠는 표준 HTML 요소 단락 태그, 호환되지 않는 공백, <table> s 등을 사용하여 CSS(계단식 스타일시트) 기술을 통해 배치할 수 있습니다. 지금까지 모든 자습서는 위치 지정에 CSS 기술을 사용했습니다. 마스터 페이지 및 사이트 탐색 자습서의 마스터 페이지에서 탐색 사용자 인터페이스를 빌드할 때 탐색 목록 및 기본 콘텐츠에 대한 정확한 픽셀 오프셋을 나타내는 절대 위치 지정을 사용했습니다. 또는 CSS를 사용하여 부동을 통해 한 요소를 다른 요소의 오른쪽 또는 왼쪽에 배치할 수 있습니다. DataList 왼쪽에 반복기를 부동하여 선택한 범주 제품의 왼쪽에 범주의 글머리 기호 목록을 표시하도록 할 수 있습니다.

폴더에서 CategoriesAndProducts.aspx DataListRepeaterFiltering 페이지를 열고 페이지에 Repeater 및 DataList를 추가합니다. 반복기를 ID Categories 로 설정하고 DataList를 로 CategoryProducts설정합니다. 원본 보기로 이동하여 반복기 및 DataList 컨트롤을 자체 <div> 요소 내에 배치합니다. 즉, 먼저 요소 내에 <div> 반복기를 묶은 다음, 반복기 바로 다음에 자체 <div> 요소의 DataList를 묶습니다. 이 시점에서의 태그는 다음과 유사합니다.

<div>
    <asp:Repeater ID="Categories" runat="server">
    </asp:Repeater>
</div>
<div>
    <asp:DataList ID="CategoryProducts" runat="server">
    </asp:DataList>
</div>

DataList의 왼쪽에 반복기를 부동하려면 다음과 같이 CSS 스타일 특성을 사용해야 float 합니다.

<div>
    Repeater
</div>
<div>
    DataList
</div>

float: left; 첫 번째 <div> 요소를 두 번째 요소의 왼쪽에 부동합니다. 및 설정은 width 요소의 width 콘텐츠와 오른쪽 여백 사이에 <div> 추가되는 안쪽 여백의 양과 첫 번째 <div> s를 padding-right 나타냅니다. CSS의 부동 요소에 대한 자세한 내용은 Floatutorial을 확인하세요.

첫 번째 <p> 요소의 style 특성을 통해 직접 스타일 설정을 지정하는 대신 다음과 같은 이름으로 FloatLeft새 CSS 클래스 Styles.css 를 만들어 보겠습니다.

.FloatLeft
{
    float: left;
    width: 33%;
    padding-right: 10px;
}

그런 다음 , 로 <div class="FloatLeft">바꿀 <div> 수 있습니다.

CSS 클래스를 추가하고 페이지에서 태그를 CategoriesAndProducts.aspx 구성한 후 디자이너로 이동합니다. DataList의 왼쪽에 떠 있는 반복기가 표시됩니다(데이터 원본 또는 템플릿을 아직 구성하지 않았기 때문에 지금은 둘 다 회색 상자로 표시됨).

반복기가 DataList의 왼쪽에 부동

그림 2: 반복기가 DataList의 왼쪽에 부동입니다(전체 크기 이미지를 보려면 클릭).

2단계: 각 범주에 대한 제품 수 결정

Repeater 및 DataList의 주변 태그가 완료되면 범주 데이터를 Repeater 컨트롤에 바인딩할 준비가 되었습니다. 그러나 그림 1의 글머리 기호 목록과 같이 각 범주 이름 외에도 범주와 연결된 제품 수를 표시해야 합니다. 이 정보에 액세스하려면 다음 중 하나를 수행할 수 있습니다.

  • ASP.NET 페이지의 코드 숨김 클래스에서 이 정보를 확인합니다. 특정 categoryID 한 경우 클래스의 GetProductsByCategoryID(categoryID) 메서드를 호출 ProductsBLL 하여 연결된 제품의 수를 확인할 수 있습니다. 이 메서드는 지정된 제품의 수인 Count 존재 횟수를 나타내는 ProductsRow 속성이 있는 개체를 반환 ProductsDataTable 합니다categoryID. Repeater에 바인딩된 각 범주에 대해 클래스의 GetProductsByCategoryID(categoryID) 메서드를 호출 ProductsBLL 하고 출력에 해당 수를 포함하는 반복기에 대한 이벤트 처리기를 만들 ItemDataBound 수 있습니다.
  • CategoriesDataTable 형식화된 데이터 세트의 열을 포함 NumberOfProducts 하도록 업데이트합니다. 그런 다음, 이 정보를 포함하도록 메서드를 CategoriesDataTable 업데이트 GetCategories() 하거나 그대로 두고 GetCategories() 새 메서드인 GetCategoriesAndNumberOfProducts()CategoriesDataTable를 만들 수 있습니다.

이 두 가지 기술을 모두 살펴보겠습니다. 첫 번째 방법은 데이터 액세스 계층을 업데이트할 필요가 없으므로 구현하는 것이 더 간단합니다. 그러나 데이터베이스와 더 많은 통신이 필요합니다. 이벤트 처리기에서 클래스의 GetProductsByCategoryID(categoryID) 메서드를 ItemDataBound 호출 ProductsBLL 하면 Repeater에 표시되는 각 범주에 대한 추가 데이터베이스 호출이 추가됩니다. 이 기술을 사용하면 N + 1 데이터베이스 호출이 있으며 여기서 N 은 리피터에 표시되는 범주의 수입니다. 두 번째 방법을 사용하면 클래스(또는GetCategoriesAndNumberOfProducts()) 메서드의 GetCategories() 각 범주 CategoriesBLL 에 대한 정보와 함께 제품 수가 반환되므로 데이터베이스를 한 번만 이동하게 됩니다.

ItemDataBound 이벤트 처리기의 제품 수 확인

Repeater 이벤트 처리기에서 각 범주의 ItemDataBound 제품 수를 결정해도 기존 데이터 액세스 계층을 수정할 필요가 없습니다. 모든 수정은 페이지 내에서 CategoriesAndProducts.aspx 직접 수행할 수 있습니다. 먼저 Repeater의 스마트 태그를 통해 명명된 CategoriesDataSource 새 ObjectDataSource를 추가합니다. 다음으로, 클래스의 CategoriesDataSource GetCategories() 메서드에서 해당 데이터를 검색할 수 있도록 ObjectDataSource를 CategoriesBLL 구성합니다.

CategoriesBLL 클래스의 GetCategories() 메서드를 사용하도록 ObjectDataSource 구성

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

반복기에서 Categories 각 항목을 클릭할 수 있어야 하며, 클릭하면 CategoryProducts DataList가 선택한 범주에 대해 해당 제품을 표시합니다. 이 작업은 각 범주를 하이퍼링크로 만들고 이 동일한 페이지(CategoriesAndProducts.aspx)에 다시 연결하지만 이전 자습서에서 보았던 것처럼 쿼리 문자열을 통해 전달 CategoryID 하여 수행할 수 있습니다. 이 방법의 장점은 특정 범주의 제품을 표시하는 페이지를 검색 엔진에서 책갈피로 지정하고 인덱싱할 수 있다는 것입니다.

또는 각 범주를 LinkButton으로 만들 수 있습니다. 이 방법은 이 자습서에 사용할 방법입니다. LinkButton은 사용자의 브라우저에서 하이퍼링크로 렌더링되지만 클릭하면 포스트백을 유도합니다. 포스트백 시 선택한 범주에 속하는 제품을 표시하려면 DataList의 ObjectDataSource를 새로 고쳐야 합니다. 이 자습서에서는 LinkButton을 사용하는 것보다 하이퍼링크를 사용하는 것이 더 적합합니다. 그러나 LinkButton을 사용하는 것이 더 유리한 다른 시나리오가 있을 수 있습니다. 하이퍼링크 접근 방식이 이 예제에 이상적이지만 LinkButton을 사용하여 탐색해 보겠습니다. 여기서 볼 수 있듯이 LinkButton을 사용하면 하이퍼링크에서 발생하지 않는 몇 가지 문제가 발생합니다. 따라서 이 자습서에서 LinkButton을 사용하면 이러한 문제를 강조하고 하이퍼링크 대신 LinkButton을 사용할 수 있는 시나리오에 대한 솔루션을 제공하는 데 도움이 됩니다.

참고 항목

LinkButton 대신 HyperLink 컨트롤 또는 <a> 요소를 사용하여 이 자습서를 반복하는 것이 좋습니다.

다음 태그는 Repeater 및 ObjectDataSource에 대한 선언적 구문을 보여 줍니다. Repeater 템플릿은 각 항목을 LinkButton으로 사용하여 글머리 기호 목록을 렌더링합니다.

<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><asp:LinkButton runat="server" ID="ViewCategory"></asp:LinkButton></li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

참고 항목

이 자습서의 경우 반복기는 뷰 상태를 사용하도록 설정해야 합니다(Repeater의 EnableViewState="False" 선언적 구문에서 생략됨). 3단계에서는 DataList의 ItemCommand ObjectDataSource SelectParameters 컬렉션을 업데이트할 Repeater 이벤트에 대한 이벤트 처리기를 만듭니다. 그러나 뷰 상태를 사용하지 않도록 설정하면 반복기가 ItemCommand실행되지 않습니다.

속성 값이 있는 ID LinkButton에는 ViewCategory 해당 속성 집합이 Text 없습니다. 범주 이름을 표시하려는 경우 다음과 같이 데이터 바인딩 구문을 통해 Text 속성을 선언적으로 설정했을 것입니다.

<asp:LinkButton runat="server" ID="ViewCategory"
    Text='<%# Eval("CategoryName") %>' />

그러나 범주 이름과 해당 범주에 속하는 제품 수를 모두 표시하려고 합니다. 이 정보는 다음 코드와 같이 클래스의 ItemDataBound 메서드를 호출 ProductBLL 하고 결과ProductsDataTable에서 반환되는 레코드 수를 결정하여 Repeater의 GetCategoriesByProductID(categoryID) 이벤트 처리기에서 검색할 수 있습니다.

Protected Sub Categories_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
    ' Make sure we're working with a data item...
    If e.Item.ItemType = ListItemType.Item OrElse _
        e.Item.ItemType = ListItemType.AlternatingItem Then
        ' Reference the CategoriesRow instance bound to this RepeaterItem
        Dim category As Northwind.CategoriesRow = _
            CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
                Northwind.CategoriesRow)
        ' Determine how many products are in this category
        Dim productsAPI As New NorthwindTableAdapters.ProductsTableAdapter
        Dim productCount As Integer = _
            productsAPI.GetProductsByCategoryID(category.CategoryID).Count
        ' Reference the ViewCategory LinkButton and set its Text property
        Dim ViewCategory As LinkButton = _
            CType(e.Item.FindControl("ViewCategory"), LinkButton)
        ViewCategory.Text = _
            String.Format("{0} ({1:N0})", category.CategoryName, productCount)
    End If
End Sub

먼저 데이터 항목(ItemType Item 해당 항목 또는 AlternatingItem)으로 작업한 다음 현재RepeaterItem에 바인딩된 인스턴스를 참조 CategoriesRow 합니다. 다음으로 클래스의 인스턴스 ProductsBLL 를 만들고, 메서드를 호출 GetCategoriesByProductID(categoryID) 하고, 속성을 사용하여 Count 반환된 레코드 수를 결정하여 이 범주에 대한 제품 수를 결정합니다. 마지막으로 ItemTemplate의 ViewCategory LinkButton은 참조이며 해당 Text 속성은 CategoryName(NumberOfProductsInCategory)으로 설정됩니다. 여기서 NumberOfProductsInCategory는 소수 자릿수가 0인 숫자로 서식이 지정됩니다.

참고 항목

또는 범주 및 값을 허용하고 범주 CategoryName 의 제품 수와 CategoryID 연결된 값을 반환 CategoryName 하는 ASP.NET 페이지의 코드 숨김 클래스에 서식 함수를 추가할 수 있습니다(메서드를 호출 GetCategoriesByProductID(categoryID) 하여 결정됨). 이러한 서식 함수의 결과는 이벤트 처리기의 필요성을 대체하여 LinkButton의 Text 속성에 ItemDataBound 선언적으로 할당될 수 있습니다. 서식 함수 사용에 대한 자세한 내용은 GridView 컨트롤의 TemplateFields 사용 또는 데이터 목록 및 반복기 기반 데이터 기반 서식 지정 자습서를 참조하세요.

이 이벤트 처리기를 추가한 후 잠시 시간을 내어 브라우저를 통해 페이지를 테스트합니다. 각 범주가 글머리 기호 목록에 나열되어 범주 이름과 범주와 연결된 제품 수를 표시하는 방법을 확인합니다(그림 4 참조).

각 범주의 이름과 제품 수가 표시됩니다.

그림 4: 각 범주의 이름과 제품 수가 표시됩니다(전체 크기 이미지를 보려면 클릭).

각 범주에CategoriesDataTable대한 제품 수 업데이트 및CategoriesTableAdapter포함

Repeater에 바인딩된 각 범주의 제품 수를 결정하는 대신 데이터 액세스 계층에서 이 정보를 기본적으로 포함하도록 조정하여 CategoriesDataTable CategoriesTableAdapter 이 프로세스를 간소화할 수 있습니다. 이렇게 하려면 연결된 제품 수를 저장할 새 열을 CategoriesDataTable 추가해야 합니다. DataTable에 새 열을 추가하려면 형식화된 데이터 세트()App_Code\DAL\Northwind.xsd를 열고 수정할 DataTable을 마우스 오른쪽 단추로 클릭하고 추가/열을 선택합니다. 새 열을 CategoriesDataTable 추가합니다(그림 5 참조).

CategoriesDataSource에 새 열 추가

그림 5: 새 열에 CategoriesDataSource 추가(전체 크기 이미지를 보려면 클릭)

이렇게 하면 이름이 Column1새 열이 추가되며, 다른 이름을 입력하기만 하면 변경할 수 있습니다. 이 새 열의 이름을 .로 NumberOfProducts바꿉니다. 다음으로 이 열의 속성을 구성해야 합니다. 새 열을 클릭하고 속성 창 이동합니다. 그림 6에 표시된 것처럼 열의 DataType 속성을 원래 System.String System.Int32 대로 변경하고 ReadOnly 속성을 설정하세요 True.

새 열의 DataType 및 ReadOnly 속성 설정

그림 6: 새 열의 DataType 속성 및 ReadOnly 설정

이제 열이 CategoriesDataTable 있지만 NumberOfProducts 해당 TableAdapter 쿼리에 의해 해당 값이 설정되지 않습니다. 범주 정보를 검색할 때마다 이러한 정보를 반환하려는 경우 이 정보를 반환하도록 메서드를 업데이트 GetCategories() 할 수 있습니다. 그러나 드문 경우(예: 이 자습서의 경우처럼) 범주에 대한 관련 제품 수만 확보하면 그대로 두고 GetCategories() 이 정보를 반환하는 새 메서드를 만들 수 있습니다. 이 후자의 방법을 사용하여 새 GetCategoriesAndNumberOfProducts()메서드를 만들어 보겠습니다.

이 새 GetCategoriesAndNumberOfProducts() 메서드를 추가하려면 해당 메서드를 CategoriesTableAdapter 마우스 오른쪽 단추로 클릭하고 새 쿼리를 선택합니다. 그러면 이전 자습서에서 여러 번 사용한 TableAdapter 쿼리 구성 마법사가 나타납니다. 이 메서드의 경우 쿼리가 행을 반환하는 임시 SQL 문을 사용함을 나타내며 마법사를 시작합니다.

임시 SQL 문을 사용하여 메서드 만들기

그림 7: 임시 SQL 문을 사용하여 메서드 만들기(전체 크기 이미지를 보려면 클릭)

SQL 문은 행을 반환합니다.

그림 8: SQL 문이 행을 반환합니다(전체 크기 이미지를 보려면 클릭).

다음 마법사 화면에서 사용할 쿼리를 묻는 메시지가 표시됩니다. 범주와 연결된 제품 수와 함께 각 범주 CategoryIDCategoryNameDescription 필드를 반환하려면 다음 SELECT 문을 사용합니다.

SELECT CategoryID, CategoryName, Description,
       (SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
            as NumberOfProducts
FROM Categories c

사용할 쿼리 지정

그림 9: 사용할 쿼리 지정(전체 크기 이미지를 보려면 클릭)

범주와 연결된 제품 수를 계산하는 하위 쿼리는 별칭으로 NumberOfProducts지정됩니다. 이 명명 일치를 사용하면 이 하위 쿼리에서 반환된 값이 해당 NumberOfProducts 열과 CategoriesDataTable 연결됩니다.

이 쿼리를 입력한 후 마지막 단계는 새 메서드의 이름을 선택하는 것입니다. GetCategoriesAndNumberOfProducts DataTable 채우기 및 DataTable 패턴 반환에 각각 사용합니다FillWithNumberOfProducts.

새 TableAdapter의 메서드 FillWithNumberOfProducts 및 GetCategoriesAndNumberOfProducts의 이름을 지정합니다.

그림 10: 새 TableAdapter의 메서드 FillWithNumberOfProducts 이름을 지정하고 GetCategoriesAndNumberOfProducts (전체 크기 이미지를 보려면 클릭)

이 시점에서 데이터 액세스 계층은 범주당 제품 수를 포함하도록 확장되었습니다. 모든 프레젠테이션 계층은 별도의 비즈니스 논리 계층을 통해 DAL에 대한 모든 호출을 라우팅하므로 해당 GetCategoriesAndNumberOfProducts 메서드를 클래스에 CategoriesBLL 추가해야 합니다.

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetCategoriesAndNumberOfProducts() As Northwind.CategoriesDataTable
    Return Adapter.GetCategoriesAndNumberOfProducts()
End Function

DAL 및 BLL이 완료되면 이 데이터를 반복기!에 바인딩할 Categories 준비가 되었습니다 CategoriesAndProducts.aspx. 이벤트 처리기 섹션의 제품 ItemDataBound 수 확인 섹션에서 반복기에 대한 ObjectDataSource를 이미 만든 경우 이 ObjectDataSource를 삭제하고 반복기의 DataSourceID 속성 설정을 제거합니다. 또한 ASP.NET 코드 숨김 클래스의 ItemDataBound 구문을 제거하여 Handles Categories.OnItemDataBound 이벤트 처리기에서 Repeater의 이벤트 연결을 해제합니다.

반복기를 원래 상태로 되돌리면 Repeater의 스마트 태그를 통해 명명된 CategoriesDataSource 새 ObjectDataSource를 추가합니다. 클래스를 사용하도록 CategoriesBLL ObjectDataSource를 구성하지만 메서드를 대신 사용하도록 GetCategories() GetCategoriesAndNumberOfProducts() 합니다(그림 11 참조).

GetCategoriesAndNumberOfProducts 메서드를 사용하도록 ObjectDataSource 구성

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

다음으로, LinkButton의 Text 속성이 데이터 바인딩 구문을 사용하여 선언적으로 할당되고 데이터 필드와 NumberOfProducts 데이터 필드를 모두 CategoryName 포함하도록 업데이트 ItemTemplate 합니다. Repeater 및 CategoriesDataSource ObjectDataSource에 대한 전체 선언적 태그는 다음과 같습니다.

<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><asp:LinkButton runat="server" ID="ViewCategory"
                Text='<%# String.Format("{0} ({1:N0})", _
                    Eval("CategoryName"), Eval("NumberOfProducts")) %>' />
        </li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoriesAndNumberOfProducts" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

열을 포함 NumberOfProducts 하도록 DAL을 업데이트하여 렌더링되는 출력은 이벤트 처리기 접근 방식을 사용하는 ItemDataBound 것과 동일합니다(범주 이름과 제품 수를 보여 주는 반복기의 스크린샷을 보려면 그림 4를 참조하세요).

3단계: 선택한 범주 제품 표시

이 시점에서 Categories 리피터는 각 범주의 제품 수와 함께 범주 목록을 표시합니다. 반복기는 각 범주에 대해 LinkButton을 사용하며, 클릭하면 포스트백이 발생하며, 이때 DataList에서 CategoryProducts 선택한 범주에 대해 해당 제품을 표시해야 합니다.

우리가 직면한 한 가지 과제는 DataList가 선택한 범주에 대한 제품만 표시하도록 하는 것입니다. Details DetailsView 자습서와 함께 선택 가능한 마스터 GridView를 사용하는 마스터/세부 정보 자습서에서는 선택한 행의 세부 정보가 같은 페이지의 DetailsView에 표시되어 행을 선택할 수 있는 GridView를 빌드하는 방법을 알아보았습니다. GridView의 ObjectDataSource는 S GetProducts() 메서드를 사용하여 ProductsBLL 모든 제품에 대한 정보를 반환했으며 DetailsView의 ObjectDataSource는 이 메서드를 사용하여 GetProductsByProductID(productID) 선택한 제품에 대한 정보를 검색했습니다. 매개 변수 값은 productID GridView SelectedValue 속성의 값과 연결하여 선언적으로 제공되었습니다. 아쉽게도 Repeater에는 속성이 SelectedValue 없으며 매개 변수 원본으로 사용할 수 없습니다.

참고 항목

이는 반복기에서 LinkButton을 사용할 때 나타나는 문제 중 하나입니다. 대신 하이퍼링크를 사용하여 querystring을 통해 전달 CategoryID 했다면 해당 QueryString 필드를 매개 변수 값의 원본으로 사용할 수 있습니다.

그러나 Repeater에 대한 속성이 SelectedValue 없다는 것을 걱정하기 전에 먼저 DataList를 ObjectDataSource에 바인딩하고 지정 ItemTemplate해 보겠습니다.

DataList의 스마트 태그에서 명명 CategoryProductsDataSource 된 새 ObjectDataSource를 추가하고 클래스의 GetProductsByCategoryID(categoryID) 메서드를 사용하도록 ProductsBLL 구성합니다. 이 자습서의 DataList는 읽기 전용 인터페이스를 제공하므로 INSERT, UPDATE 및 DELETE 탭의 드롭다운 목록을 (없음)으로 자유롭게 설정할 수 있습니다.

ProductsBLL 클래스의 GetProductsByCategoryID(categoryID) 메서드를 사용하도록 ObjectDataSource 구성

그림 12: Class s GetProductsByCategoryID(categoryID) 메서드를 사용하도록 ProductsBLL ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)

메서드는 GetProductsByCategoryID(categoryID) 입력 매개 변수(categoryID)를 예상하기 때문에 데이터 원본 구성 마법사를 사용하여 매개 변수의 원본을 지정할 수 있습니다. 범주가 GridView 또는 DataList에 나열된 경우 매개 변수 원본 드롭다운 목록을 Control로 설정하고 ControlID를 ID 데이터 웹 컨트롤로 설정했습니다. 그러나 Repeater에는 속성이 없으므로 SelectedValue 매개 변수 원본으로 사용할 수 없습니다. 확인하면 ControlID 드롭다운 목록에 DataList의 컨트롤 ID``CategoryProductsID 이 하나만 포함되어 있음을 알 수 있습니다.

지금은 매개 변수 원본 드롭다운 목록을 None으로 설정합니다. 반복기에서 LinkButton 범주를 클릭하면 프로그래밍 방식으로 이 매개 변수 값을 할당하게 됩니다.

categoryID 매개 변수에 대한 매개 변수 원본 지정 안 함

그림 13: 매개 변수의 categoryID 매개 변수 원본 지정 안 함(전체 크기 이미지를 보려면 클릭)

데이터 원본 구성 마법사를 완료한 후 Visual Studio는 DataList ItemTemplate를 자동으로 생성합니다. 이 기본값 ItemTemplate 을 이전 자습서에서 사용한 템플릿으로 바꾸고 DataList의 RepeatColumns 속성을 2로 설정합니다. 이러한 변경을 수행한 후 DataList 및 연결된 ObjectDataSource에 대한 선언적 태그는 다음과 같이 표시됩니다.

<asp:DataList ID="CategoryProducts" runat="server" DataKeyField="ProductID"
    DataSourceID="CategoryProductsDataSource" RepeatColumns="2"
    EnableViewState="False">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="CategoryProductsDataSource"
    OldValuesParameterFormatString="original_{0}"  runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:Parameter Name="categoryID" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

현재 CategoryProductsDataSource ObjectDataSource의 categoryID 매개 변수는 설정되지 않으므로 페이지를 볼 때 제품이 표시되지 않습니다. 이 매개 변수 값은 반복기에서 클릭한 범주에 따라 CategoryID 설정해야 합니다. 이렇게 하면 두 가지 문제가 발생합니다. 첫째, Repeater의 ItemTemplate LinkButton을 클릭한 시기를 어떻게 결정해야 하며, 둘째, LinkButton을 클릭한 해당 범주를 어떻게 확인할 CategoryID 수 있나요?

Button 및 ImageButton 컨트롤과 같은 LinkButton에는 Click 이벤트와 이벤트가 있습니다Command. 이 Click 이벤트는 LinkButton이 클릭되었음을 기록하기 위해 설계되었습니다. 그러나 때때로 LinkButton을 클릭했다는 것 외에도 이벤트 처리기에 몇 가지 추가 정보를 전달해야 합니다. 이 경우 LinkButton CommandNameCommandArgument 속성에 이 추가 정보를 할당할 수 있습니다. 그런 다음 LinkButton을 클릭하면 Command 이벤트가 이벤트 대신 Click 실행되고 이벤트 처리기가 해당 및 CommandArgument 속성의 CommandName 값을 전달합니다.

Command Repeater의 템플릿 내에서 이벤트가 발생하면 Repeater 이벤트가 ItemCommand 발생하고 클릭한 LinkButton(또는 Button 또는 ImageButton)의 값과 CommandArgument 값이 전달 CommandName 됩니다. 따라서 반복기에서 범주 LinkButton을 클릭한 시기를 확인하려면 다음을 수행해야 합니다.

  1. CommandName 반복 ItemTemplate 기에서 LinkButton의 속성을 일부 값으로 설정합니다(ListProducts를 사용했습니다). 이 CommandName 값을 설정하면 LinkButton을 Command 클릭하면 LinkButton 이벤트가 발생합니다.
  2. LinkButton의 CommandArgument 속성을 현재 항목 CategoryID의 값으로 설정합니다.
  3. Repeater 이벤트에 대한 이벤트 처리기를 ItemCommand 만듭니다. 이벤트 처리기에서 ObjectDataSource의 CategoryID 매개 변수를 전달된 CommandArgument값으로 설정합니다CategoryProductsDataSource.

범주 반복기에서 다음 ItemTemplate 태그는 1단계와 2단계를 구현합니다. 데이터 바인딩 구문을 사용하여 값에 데이터 항목 CategoryID 이 할당되는 방식을 CommandArgument 확인합니다.

<ItemTemplate>
    <li>
        <asp:LinkButton CommandName="ListProducts"  runat="server"
            CommandArgument='<%# Eval("CategoryID") %>' ID="ViewCategory"
            Text='<%# string.Format("{0} ({1:N0})", _
                Eval("CategoryName"), Eval("NumberOfProducts")) %>'>
        </asp:LinkButton>
    </li>
</ItemTemplate>

이벤트 처리기를 만들 ItemCommand 때마다 항상 먼저 들어오는 CommandName 값을 확인하는 것이 좋습니다. 반복기 내의 Button, LinkButton 또는 ImageButton에서 발생한 모든 이벤트가 이벤트를 발생시킬 수 ItemCommand 있기 Command 때문입니다. 현재는 이러한 LinkButton이 하나뿐이지만 나중에 우리(또는 우리 팀의 다른 개발자)는 반복기에 단추 웹 컨트롤을 추가하여 클릭할 때 동일한 ItemCommand 이벤트 처리기를 발생시킬 수 있습니다. 따라서 항상 속성을 확인하고 CommandName 예상 값과 일치하는 경우에만 프로그래밍 논리를 진행하는 것이 가장 좋습니다.

전달된 CommandName 값이 ListProducts와 같은지 확인한 후 이벤트 처리기는 ObjectDataSource의 CategoryID 매개 변수를 전달된 값에 CommandArgument할당 CategoryProductsDataSource 합니다. ObjectDataSource를 SelectParameters 자동으로 수정하면 DataList가 데이터 원본에 다시 바인딩되어 새로 선택한 범주의 제품이 표시됩니다.

Protected Sub Categories_ItemCommand(source As Object, e As RepeaterCommandEventArgs) _
    Handles Categories.ItemCommand
    ' If it's the "ListProducts" command that has been issued...
    If String.Compare(e.CommandName, "ListProducts", True) = 0 Then
        ' Set the CategoryProductsDataSource ObjectDataSource's CategoryID parameter
        ' to the CategoryID of the category that was just clicked (e.CommandArgument)...
        CategoryProductsDataSource.SelectParameters("CategoryID").DefaultValue = _
            e.CommandArgument.ToString()
    End If
End Sub

이러한 추가 기능으로 자습서가 완료되었습니다. 잠시 시간을 내어 브라우저에서 테스트합니다. 그림 14는 페이지를 처음 방문할 때의 화면을 보여줍니다. 범주를 아직 선택하지 않았으므로 제품이 표시되지 않습니다. 제품과 같은 범주를 클릭하면 제품 범주에 해당 제품이 2열 보기로 표시됩니다(그림 15 참조).

페이지를 처음 방문할 때 제품이 표시되지 않음

그림 14: 페이지를 처음 방문할 때 제품이 표시되지 않음(전체 크기 이미지를 보려면 클릭)

제품 범주를 클릭하면 오른쪽에 일치하는 제품이 나열됩니다.

그림 15: 제품 범주를 클릭하면 오른쪽에 일치하는 제품이 나열됩니다(전체 크기 이미지를 보려면 클릭).

요약

이 자습서와 이전 자습서에서 보았듯이 마스터/세부 보고서는 두 페이지에 분산되거나 하나로 통합될 수 있습니다. 그러나 단일 페이지에 마스터/세부 정보 보고서를 표시하면 마스터 및 세부 정보 레코드를 페이지에 레이아웃하는 가장 좋은 방법에 대한 몇 가지 문제가 발생합니다. DetailsView 자습서와 함께 선택 가능한 마스터 GridView를 사용하는 마스터/세부 정보 자습서에서는 세부 정보 레코드가 마스터 레코드 위에 표시되도록 했습니다. 이 자습서에서는 CSS 기술을 사용하여 마스터 레코드가 세부 정보의 왼쪽에 부동하도록 했습니다.

마스터/세부 정보 보고서 표시와 함께 각 범주와 연결된 제품 수를 검색하는 방법뿐만 아니라 리피터 내에서 LinkButton(또는 Button 또는 ImageButton)을 클릭할 때 서버 쪽 논리를 수행하는 방법도 살펴볼 수 있었습니다.

이 자습서에서는 DataList 및 Repeater를 사용하여 마스터/세부 보고서 검사를 완료합니다. 다음 자습서 집합에서는 편집 및 삭제 기능을 DataList 컨트롤에 추가하는 방법을 보여 줍니다.

행복한 프로그래밍!

추가 정보

이 자습서에서 설명하는 항목에 대한 자세한 내용은 다음 리소스를 참조하세요.

  • CSS를 사용하여 부동 CSS 요소에 대한 자습서 부동
  • CSS를 사용하여 요소 위치 지정에 대한 자세한 정보 위치 지정
  • 위치 지정을 위해 s 및 기타 HTML 요소를 사용하여 <table> HTML로 콘텐츠 배치

작성자 정보

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

특별 감사

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 Zack Jones였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 선을 놓습니다 mitchell@4GuysFromRolla.com.