연습: JavaScript에서 데이터 바인딩 컨트롤에 더 쉽게 액세스할 수 있도록 만들기

이 연습에서는 클라이언트 스크립트에서 데이터 바인딩된 컨트롤에 액세스하는 방법을 보여 줍니다. 이 연습에서는 AdventureWorksLT 샘플 데이터베이스의 Products 테이블에 있는 제품 이름 및 가격의 목록을 표시하는 웹 페이지를 만듭니다. 주기적으로 웹 서비스를 호출하여 변경된 가격을 모두 검색하고 업데이트하는 클라이언트 스크립트를 추가합니다. 그런 다음 전체 페이지를 새로 고치지 않고 새 정보만 표시하도록 페이지를 업데이트합니다.

제품 정보는 ListView 컨트롤의 Label 컨트롤에 표시됩니다. HTML에서 Label 컨트롤은 id 특성이 있는 span 요소로 렌더링됩니다. 클라이언트 스크립트를 사용하는 경우 span 요소를 참조하여 해당 텍스트를 변경하기 위한 가장 쉬운 방법은 document.getElementById 메서드를 사용하는 것입니다. 이 메서드를 사용하려면 span 요소의 id 특성 값을 알아야 합니다.

ASP.NET에서 예측할 수 있는 id 값이 생성되도록 하기 위해 ListView 컨트롤의 ClientIDModeClientIDRowSuffix 속성을 설정하면 제품 ID가 포함된 id 특성 값이 생성됩니다. 웹 서비스에서 ProductID 값과 변경된 가격을 반환하고 ProductID는 id 특성에 있으므로 개별 제품에 대해 변경해야 하는 span 요소를 쉽게 찾을 수 있습니다.

이 연습을 실행하려면 다음 사항이 준비되어 있어야 합니다.

이 연습 단원에서는 나중에 클라이언트 스크립트를 사용하여 액세스할 수 있는 데이터 바인딩된 컨트롤이 포함된 페이지를 만듭니다. 클라이언트 스크립트에서 컨트롤의 인스턴스에 쉽게 액세스할 수 있도록 하기 위해 데이터 바인딩된 컨트롤의 ClientIDMode 속성을 설정하여 해당 컨트롤에서 예측 가능한 id 특성을 만들 수 있습니다.

예측 가능한 클라이언트 식별자를 생성하는 웹 페이지를 만들려면

  1. Visual Studio에서 ProductList.aspx라는 새 웹 페이지를 만듭니다.

  2. 솔루션 탐색기에서 새 페이지를 마우스 오른쪽 단추로 클릭하고 시작 페이지로 설정을 클릭합니다.

  3. 디자인 뷰로 전환합니다.

  4. 도구 상자에서 SqlDataSource 컨트롤을 웹 페이지로 끌어옵니다.

  5. AdventureWorksLT 데이터베이스에 연결한 후 Product 테이블의 모든 행에 대해 ProductID, Name 및 ListPrice 열을 선택하는 사용자 지정 SQL 문을 사용하도록 SqlDataSource 컨트롤을 구성합니다.

  6. 소스 뷰로 전환합니다.

    컨트롤의 태그는 다음 예제와 유사합니다.

    
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
        ConnectionString="<%$ ConnectionStrings:AdventureWorksLTConnectionString %>"
        SelectCommand="SELECT ProductID, Name, ListPrice FROM SalesLT.Product">
    </asp:SqlDataSource>
    
    
    
  7. 열고 닫는 <div> 태그 사이에 다음 태그를 추가합니다.

    
    <table>
        <tr>
            <th>Product ID</th>
            <th>Product Name</th>
            <th>List Price</th>
        </tr>
        <asp:ListView ID="ListView1" runat="server" 
            DataSourceID="SqlDataSource1" 
            ClientIDMode="Predictable"
            ClientIDRowSuffix="ProductID">
            <ItemTemplate>
                <tr>
                    <td><%# Eval("ProductID") %></td>
                    <td><%# Eval("Name") %></td>
                    <td align="right">
                        <asp:Label ID="PriceLabel" runat="server" 
                        Text='<%# Eval("ListPrice","{0:#.00}") %>' />
                    </td>
                </tr>
            </ItemTemplate>
            <LayoutTemplate>
                <div id="itemPlaceholderContainer" runat="server">
                    <span id="itemPlaceholder" runat="server" />
                </div>
            </LayoutTemplate>
        </asp:ListView>
    </table>
    
    
    

    이 태그는 ListView 컨트롤을 사용하여 Product ID, Product Name 및 List Price 열로 구성된 테이블을 표시합니다. 가격은 통화 형식으로 지정됩니다.

    태그에서 ListView 컨트롤의 ClientIDMode 속성이 Predictable로 설정되고 ClientIDRowSuffix 속성이 ProductID로 설정됩니다. 가격을 포함하는 렌더링된 HTML span 요소의 id 특성은 ListView1_PriceLabel_number가 되며 여기서 number는 ProductID입니다. id 패턴은 이후 단계에서 변경된 개별 가격을 업데이트하는 데 사용됩니다.

    ClientIDRowSuffix 를 데이터 필드의 이름으로 설정할 수 있습니다. 하지만 각 행에 대해 고유하지 않은 값이 포함된 필드를 선택하는 경우 HTML에서 렌더링된 id 특성이 고유하지 않을 수 있으므로 document.getElementById 메서드를 사용하여 특정 컨트롤에 대한 참조를 가져오지 못할 수도 있습니다. 또한 필드의 데이터는 id 특성에서 변경하지 않고 사용할 수 있어야 합니다. 예를 들어 공백이 포함된 필드를 선택하면 ASP.NET에서는 잘못된 id 특성이 생성됩니다.

  8. 변경 내용을 저장한 다음 Ctrl+F5를 눌러 브라우저에서 해당 페이지를 봅니다.

    ProductList.aspx 페이지를 보여주는 스크린 샷
  9. 브라우저에서 표시된 웹 페이지의 소스 코드를 봅니다.

    Label 컨트롤은 span 요소로 만들어집니다. id 특성에는 ListView1_PriceLabel_680과 같은 이름이 있으며 여기서 id의 끝에 있는 번호는 레코드에 대한 ProductID입니다.

  10. 브라우저를 닫습니다.

제품의 현재 가격을 클라이언트 스크립트에서 사용할 수 있도록 하기 위해 Product 테이블에 대한 LINQ to SQL 클래스와 변경된 가격에 대한 정보를 반환하는 AJAX 사용 웹 서비스를 만듭니다.

여러 가지 방법으로 데이터를 웹 서비스에서 사용할 수 있습니다. 이 연습에서는 비교적 사용하기 쉬운 LINQ to SQL을 사용합니다. 대체 방법에 대한 자세한 내용은 Visual Studio에서 데이터 액세스를 참조하십시오.

웹 서비스에서 Product 테이블을 사용할 수 있도록 하려면

  1. 웹 사이트에 App_Code 폴더가 없는 경우 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 ASP.NET 폴더 추가를 클릭한 다음 App_Code를 클릭합니다.

  2. 솔루션 탐색기에서 App_Code 폴더를 마우스 오른쪽 단추로 클릭한 다음 새 항목 추가를 클릭합니다.

  3. 설치된 템플릿에서 LINQ to SQL 클래스를 선택합니다.

  4. 이름 필드에 AdventureWorks.dbml을 입력하고 추가를 클릭합니다.

    개체 관계형 디자이너 창이 표시됩니다.

  5. 서버 탐색기에서 AdventureWorksLT 데이터베이스에 대한 테이블 노드를 확장합니다.

  6. Product (SalesLT) 테이블을 개체 관계형 디자이너 디자인 화면의 패널로 끌어와서 데이터 클래스를 만듭니다.

  7. 개체 관계형 디자이너 창에서 방금 만든 Product 클래스의 속성 중에서 ProductIDListPrice를 제외한 모든 속성을 삭제합니다.

  8. 개체 관계형 디자이너 창을 닫고 AdventureWorks.dbml에 변경 내용을 저장합니다.

웹 서비스 액세스를 통해 Product 테이블을 사용할 수 있도록 만든 후에는 웹 서비스 자체를 만들 수 있습니다. 이 연습에서는 AJAX를 사용하여 클라이언트 스크립트에서 직접 호출할 수 있는 웹 서비스를 만듭니다.

AJAX를 사용하여 호출할 수 있는 웹 서비스를 만들려면

  1. 솔루션 탐색기에서 웹 사이트를 마우스 오른쪽 단추로 클릭한 다음 새 항목 추가를 클릭합니다.

  2. 설치된 템플릿에서 웹 서비스를 선택합니다.

  3. 서비스에 PriceWebService.asmx라는 이름을 지정합니다.

    이렇게 하면 Visual Studio에서 PriceWebService.vb 또는 PriceWebService.cs 파일이 App_Code 폴더에 만들어지고 열립니다.

  4. System.Web.Script.Services.ScriptService 특성에 대한 주석 처리를 제거합니다.

    이렇게 해야 웹 서비스를 AJAX 호출에서 사용할 수 있습니다.

  5. HelloWorld 메서드를 다음 코드로 바꿉니다.

    
    [WebMethod]
    public Product[] GetPrices()
    {
        AdventureWorksDataContext context = new AdventureWorksDataContext();
    
        List<Product> productsToReturn = new List<Product>();
        Random randomNumber = new Random();
    
        foreach (Product p in context.Products)
        {
            if (p.ProductID % 10 == randomNumber.Next(10))
            {
                p.ListPrice += 1000;
                productsToReturn.Add(p);
            }
        }
        return productsToReturn.ToArray<Product>();
    }
    
    
    

    이 코드는 마지막으로 쿼리를 실행한 이후 가격이 변경된 제품만 반환하는 쿼리를 시뮬레이션합니다. 이 시뮬레이션에서는 테이블의 행 중에서 1/10을 임의로 선택한 후 선택한 각 행의 가격에 1000을 더한 다음 수정된 행을 호출 프로그램에 반환합니다.

  6. PriceWebService.vb 또는 PriceWebService.cs를 닫고 저장합니다.

웹 페이지에서 클라이언트 스크립트를 통해 웹 서비스를 호출하려면 웹 서비스에 대한 프록시를 만들어야 합니다. 이 작업을 수행하려면 ScriptManager 컨트롤을 페이지에 추가한 후 이전 절차에서 만든 웹 서비스에 대한 경로를 지정합니다.

웹 페이지의 클라이언트 스크립트에서 웹 서비스를 사용할 수 있도록 하려면

  1. 솔루션 탐색기에서 ProductList.aspx를 엽니다.

  2. 디자인 뷰로 전환합니다.

  3. 도구 상자에서 AJAX 확장 탭을 확장하고 ScriptManager 컨트롤을 웹 페이지로 끌어옵니다.

  4. ScriptManager 컨트롤을 마우스 오른쪽 단추로 클릭한 다음 속성을 클릭합니다.

  5. 속성 창에서 서비스 컬렉션을 확장하여 ServiceReference 컬렉션 편집기 창을 엽니다.

  6. 추가를 클릭하고 PriceWebService.asmx를 참조된 경로로 지정한 다음 확인을 클릭합니다.

  7. 소스 뷰로 전환합니다.

    ScriptManager 컨트롤에 추가된 태그는 다음 예제와 유사합니다.

    
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:servicereference Path="PriceWebService.asmx" />
        </Services>
    </asp:ScriptManager>
    
    
    

웹 페이지를 웹 서비스의 데이터로 업데이트하려면 서비스를 호출한 다음 적절한 컨트롤을 업데이트하는 클라이언트 스크립트를 추가합니다.

WCF 서비스를 호출하고 변경된 가격을 업데이트하려면

  1. ProductList.aspx가 소스 뷰에 열려 있는 상태에서 닫는 </head> 태그 앞에 다음 클라이언트 스크립트 코드를 추가합니다.

    
    <script language="javascript" type="text/javascript">
    
        //Call the web service to get changed prices.
        function UpdatePrices() {
            var pricesService = new PriceWebService();
            pricesService.GetPrices(onSuccess, onFailure, null);
            setTimeout('UpdatePrices()', 5000);
        }
    
        //Update the web page after a successful web service call.
        function onSuccess(result) {
            for (var i = 0; i < result.length; i++) {
                $get("ListView1_ListPriceLabel_" + result[i].ProductID).innerHTML = 
                    "<b>" + result[i].ListPrice.toFixed(2) + "</b>";
            }
        }
    
        function onFailure(results) {
            alert('failed');
        }
    
    </script>
    
    
    

    UpdatePrices 메서드는 웹 서비스를 비동기적으로 호출한 후 호출이 성공하면 onSuccess 메서드를 콜백 메서드로 설정합니다. 그러면 이 메서드는 5초 동안 기다린 후 자신을 다시 호출하므로 5초마다 가격이 업데이트됩니다.

    onSuccess 메서드는 WCF 서비스로부터 받은 데이터베이스 행을 반복합니다. 이 메서드는 각 항목에 대해 ProductID를 기반으로 예측된 클라이언트 id 특성을 구성한 후 $get 메서드(document.getElementById의 축약형)에서 요소를 검색하는 데 이 특성을 사용하여 요소에 새 ListPrice 값을 설정합니다. 또한 변경 내용이 잘 보이도록 새 값을 <b>(굵게) 태그로 묶습니다.

  2. 다음 예제와 같이 5초 동안 기다린 후 새 UpdatePrices 함수를 호출하는 onload 특성을 열린 <body> 태그에 추가합니다.

    
    <body onload="setTimeout('UpdatePrices()', 5000)">
    
    
    
  3. 변경 내용을 저장한 다음 Ctrl+F5를 눌러 브라우저에서 해당 페이지를 봅니다.

    해당 페이지는 이전과 동일하게 로드됩니다. 5초 후에는 전체 제품 중 10%에 해당하는 제품의 가격이 1000만큼 증가합니다. 변경된 가격은 굵게 표시됩니다. 5초마다 추가 제품의 가격이 변경됩니다.

    일부 가격이 굵게 표시된 ProductList.aspx

    ListView 컨트롤의 ClientIDMode 속성을 Predictable로 설정하지 않은 경우에는 클라이언트 id 특성이 ListView1_ctrl99_PriceLabel 형식으로 만들어집니다. 여기서 99는 항목의 상대 인덱스입니다. 웹 서비스에 대한 각 호출은 변경된 행만을 검색하므로 서비스에서 검색된 지정된 행의 상대 인덱스는 웹 페이지의 전체 목록에 있는 해당 항목의 위치와 같지 않습니다. 따라서 해당 행을 찾아서 업데이트하는 클라이언트 스크립트 코드를 작성하기는 매우 어렵습니다.

이 연습에서는 클라이언트 스크립트를 사용하여 웹 페이지에 있는 데이터 바인딩된 컨트롤에 액세스하는 방법을 살펴보았습니다. 이제부터는 ASP.NET에서 ClientID 값을 생성하는 방법과 사용자 정의 컨트롤에 대한 특별한 고려 사항에 대해 더 자세히 알아볼 수 있습니다. 다음 목록에서는 추가로 배울 수 있는 항목을 제안합니다.

표시: