DataList의 편집 인터페이스 사용자 지정(C#)

작성자 : Scott Mitchell

PDF 다운로드

이 자습서에서는 DropDownLists 및 CheckBox를 포함하는 DataList에 대한 보다 풍부한 편집 인터페이스를 만듭니다.

소개

DataList의 EditItemTemplate 태그 및 웹 컨트롤은 편집 가능한 인터페이스를 정의합니다. 지금까지 살펴본 편집 가능한 모든 DataList 예제에서 편집 가능한 인터페이스는 TextBox 웹 컨트롤로 구성되었습니다. 이전 자습서에서는 유효성 검사 컨트롤을 추가하여 편집 시간 사용자 환경을 개선했습니다.

DropDownLists EditItemTemplate , RadioButtonLists, 일정 등과 같은 TextBox 이외의 웹 컨트롤을 포함하도록 를 추가로 확장할 수 있습니다. TextBoxes와 마찬가지로 다른 웹 컨트롤을 포함하도록 편집 인터페이스를 사용자 지정할 때 다음 단계를 수행합니다.

  1. 웹 컨트롤을 에 추가합니다 EditItemTemplate.
  2. 데이터 바인딩 구문을 사용하여 해당 데이터 필드 값을 적절한 속성에 할당합니다.
  3. 이벤트 처리기 UpdateCommand 에서 프로그래밍 방식으로 웹 컨트롤 값에 액세스하여 적절한 BLL 메서드에 전달합니다.

이 자습서에서는 DropDownLists 및 CheckBox를 포함하는 DataList에 대한 보다 풍부한 편집 인터페이스를 만듭니다. 특히 제품 정보를 나열하고 제품 이름, 공급업체, 범주 및 중단된 상태 업데이트할 수 있도록 허용하는 DataList를 만듭니다(그림 1 참조).

편집 인터페이스에는 TextBox, 두 개의 DropDownList 및 CheckBox가 포함됩니다.

그림 1: 편집 인터페이스에는 TextBox, 두 개의 DropDownList 및 CheckBox가 포함되어 있습니다(전체 크기 이미지를 보려면 클릭).

1단계: 제품 정보 표시

DataList의 편집 가능한 인터페이스를 만들려면 먼저 읽기 전용 인터페이스를 빌드해야 합니다. 먼저 폴더에서 페이지를 열고 CustomizedUI.aspx Designer 페이지에 DataList를 추가하여 해당 ID 속성을 ProductsEditDeleteDataList 설정합니다. DataList의 스마트 태그에서 새 ObjectDataSource를 만듭니다. 이 새 ObjectDataSource ProductsDataSource 의 이름을 지정하고 클래스의 GetProducts 메서드에서 ProductsBLL 데이터를 검색하도록 구성합니다. 이전 편집 가능한 DataList 자습서와 마찬가지로 비즈니스 논리 계층으로 직접 이동하여 편집된 제품의 정보를 업데이트합니다. 따라서 UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록을 (없음)으로 설정합니다.

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

그림 2: 업데이트, 삽입 및 삭제 탭 Drop-Down Lists (없음)으로 설정(전체 크기 이미지를 보려면 클릭)

ObjectDataSource를 구성한 후 Visual Studio는 반환된 각 데이터 필드의 이름과 값을 나열하는 DataList에 대한 기본값 ItemTemplate 을 만듭니다. ItemTemplate 템플릿이 범주 이름, 공급업체 이름<h4>, 가격 및 중단된 상태 함께 요소의 제품 이름을 나열할 수 있도록 을 수정합니다. 또한 편집 단추를 추가하여 해당 CommandName 속성이 편집으로 설정되어 있는지 확인합니다. 내 ItemTemplate 선언적 태그는 다음과 같습니다.

<ItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="CategoryNameLabel" runat="server"
                    Text='<%# Eval("CategoryName") %>' />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="SupplierNameLabel" runat="server"
                    Text='<%# Eval("SupplierName") %>' />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="DiscontinuedLabel" runat="server"
                    Text='<%# Eval("Discontinued") %>' />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="EditButton"
                    Text="Edit" CommandName="Edit" />
            </td>
        </tr>
    </table>
    <br />
</ItemTemplate>

위의 태그는 제품 이름에 h4 제목을 사용하고 나머지 필드에는 4>열 <table> 을 사용하여 <제품 정보를 배치합니다. ProductPropertyLabel 에 정의된 Styles.cssProductPropertyValue CSS 클래스는 이전 자습서에서 설명했습니다. 그림 3은 브라우저를 통해 볼 때 진행률을 보여 드립니다.

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

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

2단계: 편집 인터페이스에 웹 컨트롤 추가

사용자 지정된 DataList 편집 인터페이스를 빌드하는 첫 번째 단계는 필요한 웹 컨트롤을 에 추가하는 것입니다 EditItemTemplate. 특히 범주에 대한 DropDownList, 공급자에 대한 또 다른 DropDownList 및 중단된 상태에 대한 CheckBox가 필요합니다. 이 예제에서는 제품 가격을 편집할 수 없으므로 레이블 웹 컨트롤을 사용하여 계속 표시할 수 있습니다.

편집 인터페이스를 사용자 지정하려면 DataList의 스마트 태그에서 템플릿 편집 링크를 클릭하고 드롭다운 목록에서 옵션을 선택합니다 EditItemTemplate . DropDownList를 에 EditItemTemplate 추가하고 를 IDCategories설정합니다.

범주에 대한 DropDownList 추가

그림 4: 범주에 대한 DropDownList 추가(전체 크기 이미지를 보려면 클릭)

그런 다음 DropDownList의 스마트 태그에서 데이터 원본 선택 옵션을 선택하고 라는 CategoriesDataSource새 ObjectDataSource를 만듭니다. 클래스의 GetCategories() 메서드를 사용하도록 이 ObjectDataSource를 CategoriesBLL 구성합니다(그림 5 참조). 다음으로 DropDownList의 데이터 원본 구성 마법사는 각 ListItem s TextValue 속성에 사용할 데이터 필드를 묻는 메시지를 표시합니다. 그림 6과 같이 DropDownList에 데이터 필드가 CategoryID 표시 CategoryName 되고 를 값으로 사용하도록 합니다.

CategoriesDataSource라는 새 ObjectDataSource 만들기

그림 5: 새 ObjectDataSource 이름 CategoriesDataSource 만들기(전체 크기 이미지를 보려면 클릭)

DropDownList의 표시 및 값 필드 구성

그림 6: DropDownList의 표시 및 값 필드 구성(전체 크기 이미지를 보려면 클릭)

이 일련의 단계를 반복하여 공급업체에 대한 DropDownList를 만듭니다. 이 DropDownList의 를 IDSuppliers 설정하고 이름을 ObjectDataSource SuppliersDataSource로 지정합니다.

두 DropDownLists를 추가한 후 중단된 상태의 CheckBox와 제품 이름에 대한 TextBox를 추가합니다. ID CheckBox 및 TextBox의 를 각각 및 ProductNameDiscontinued 설정합니다. RequiredFieldValidator를 추가하여 사용자가 제품 이름에 대한 값을 제공하는지 확인합니다.

마지막으로 업데이트 및 취소 단추를 추가합니다. 이 두 단추의 경우 해당 CommandName 속성이 각각 업데이트 및 취소로 설정되는 것이 중요합니다.

원하는 편집 인터페이스를 자유롭게 배치할 수 있습니다. 다음 선언적 구문과 스크린샷에서 보여 주듯이 읽기 전용 인터페이스에서 동일한 4열 <table> 레이아웃을 사용하도록 선택했습니다.

<EditItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Name:</td>
            <td colspan="3" class="ProductPropertyValue">
                <asp:TextBox runat="server" ID="ProductName" Width="90%" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
                    ControlToValidate="ProductName"
                    ErrorMessage="You must enter a name for the product."
                    runat="server">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Categories" runat="server"
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID" />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Suppliers" DataTextField="CompanyName"
                    DataSourceID="SuppliersDataSource"
                    DataValueField="SupplierID" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:CheckBox runat="server" id="Discontinued" />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
                    Text="Update" />
                 
                <asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
                    Text="Cancel" CausesValidation="False" />
            </td>
        </tr>
    </table>
    <br />
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
        TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
        TypeName="SuppliersBLL">
    </asp:ObjectDataSource>
</EditItemTemplate>

편집 인터페이스는 Read-Only 인터페이스처럼 배치됩니다.

그림 7: 편집 인터페이스가 Read-Only 인터페이스처럼 배치됩니다(전체 크기 이미지를 보려면 클릭).

3단계: EditCommand 및 CancelCommand 이벤트 처리기 만들기

현재 에 데이터 바인딩 구문 EditItemTemplate 이 없습니다(에서 축ItemTemplate자를 통해 복사된 를 제외하고UnitPriceLabel). 데이터 바인딩 구문을 일시적으로 추가하지만 먼저 DataList EditCommandCancelCommand 이벤트에 대한 이벤트 처리기를 만들어 보겠습니다. 이벤트 처리기의 책임 EditCommand 은 편집 단추를 클릭한 DataList 항목에 대한 편집 인터페이스를 렌더링하는 반면 CancelCommand , 작업은 DataList를 사전 편집 상태로 반환하는 것입니다.

이러한 두 이벤트 처리기를 만들고 다음 코드를 사용하도록 합니다.

protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property and rebind the data
    Products.EditItemIndex = e.Item.ItemIndex;
    Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Return to DataList to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

이러한 두 이벤트 처리기가 준비되면 편집 단추를 클릭하면 편집 인터페이스가 표시되고 취소 단추를 클릭하면 편집된 항목이 읽기 전용 모드로 반환됩니다. 그림 8은 Chef Anton의 검보 믹스에 대해 편집 단추를 클릭한 후의 DataList를 보여줍니다. 아직 편집 인터페이스 ProductName 에 데이터 바인딩 구문을 추가하지 않았으므로 TextBox가 비어 있고 CheckBox Discontinued 가 선택되지 않았으며 및 Suppliers DropDownLists에서 Categories 선택한 첫 번째 항목이 있습니다.

EditCommand 및 CancelCommand 이벤트 처리기가 추가되고 편집 단추가 선택된 후 DataList EditItemTemplate을 보여 주는 스크린샷

그림 8: 편집 단추를 클릭하면 편집 인터페이스가 표시됩니다(전체 크기 이미지를 보려면 클릭).

4단계: 편집 인터페이스에 DataBinding 구문 추가

편집 인터페이스에 현재 제품의 값이 표시되도록 하려면 데이터 바인딩 구문을 사용하여 데이터 필드 값을 적절한 웹 컨트롤 값에 할당해야 합니다. 데이터 바인딩 구문은 템플릿 편집 화면으로 이동하고 웹 컨트롤 스마트 태그에서 DataBindings 편집 링크를 선택하여 Designer 통해 적용할 수 있습니다. 또는 데이터 바인딩 구문을 선언적 태그에 직접 추가할 수 있습니다.

TextBox 속성 TextProductNameProductName 데이터 필드 값을 할당하고, CategoryIDSupplierID 데이터 필드 값을 CategoriesSuppliers DropDownLists SelectedValue 속성에 할당하고Discontinued, 데이터 필드 값을 CheckBox의 Checked 속성에 Discontinued 할당합니다. Designer 통해 또는 선언적 태그를 통해 직접 변경한 후 브라우저를 통해 페이지를 다시 방문하고 Chef Anton의 Gumbo Mix에 대한 편집 단추를 클릭합니다. 그림 9와 같이 데이터 바인딩 구문은 현재 값을 TextBox, DropDownLists 및 CheckBox에 추가했습니다.

DataBinding 구문을 추가하고 편집 단추를 선택한 후 DataList EditItemTemplate을 보여 주는 스크린샷

그림 9: 편집 단추를 클릭하면 편집 인터페이스가 표시됩니다(전체 크기 이미지를 보려면 클릭).

5단계: UpdateCommand 이벤트 처리기에서 사용자 변경 내용 저장

사용자가 제품을 편집하고 업데이트 단추를 클릭하면 포스트백이 발생하고 DataList 이벤트가 UpdateCommand 발생합니다. 이벤트 처리기에서 데이터베이스의 제품을 업데이트하려면 의 웹 컨트롤 EditItemTemplate 에서 값을 읽고 BLL과 인터페이스해야 합니다. 이전 자습서 ProductID 에서 볼 수 있듯이 업데이트된 제품의 은 컬렉션을 통해 DataKeys 액세스할 수 있습니다. 다음 코드와 같이 를 사용하여 FindControl("controlID")웹 컨트롤을 프로그래밍 방식으로 참조하여 사용자 입력 필드에 액세스합니다.

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Make sure the page is valid...
    if (!Page.IsValid)
        return;
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    DropDownList categories = (DropDownList)e.Item.FindControl("Categories");
    DropDownList suppliers = (DropDownList)e.Item.FindControl("Suppliers");
    CheckBox discontinued = (CheckBox)e.Item.FindControl("Discontinued");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    int categoryIDValue = Convert.ToInt32(categories.SelectedValue);
    int supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);
    bool discontinuedValue = discontinued.Checked;
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue,
                              discontinuedValue, productID);
    // Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

코드는 페이지의 모든 유효성 검사 컨트롤이 Page.IsValid 유효한지 확인하기 위해 속성을 참조하여 시작합니다. 이 이TruePage.IsValid 편집된 제품의 ProductID 값이 컬렉션에서 DataKeys 읽혀지고 의 데이터 항목 웹 컨트롤 EditItemTemplate 이 프로그래밍 방식으로 참조됩니다. 다음으로, 이러한 웹 컨트롤의 값을 변수로 읽은 다음 적절한 UpdateProduct 오버로드에 전달합니다. 데이터를 업데이트한 후 DataList는 사전 편집 상태로 반환됩니다.

참고

코드와 이 예제를 집중하기 위해 BLL 처리 및 DAL-Level 예외 처리 자습서에 추가된 예외 처리 논리를 생략했습니다. 연습으로 이 자습서를 완료한 후 이 기능을 추가합니다.

6단계: NULL CategoryID 및 SupplierID 값 처리

Northwind 데이터베이스는 테이블 CategoryIDSupplierID 열에 Products 대한 NULL 값을 허용합니다. 그러나 편집 인터페이스는 현재 값을 수용 NULL 하지 않습니다. 해당 또는 열에 대한 값이 있는 NULL 제품을 편집하려고 하면 다음과 유사한 오류 메시지가 표시됩니다. 'Categories'에는 항목 목록에 존재하지 않기 때문에 잘못된 SelectedValue가 있습니다.ArgumentOutOfRangeExceptionSupplierIDCategoryID 또한 현재 제품의 범주 또는 공급자 값을 비값NULL에서 1로 변경할 수 있는 NULL 방법은 없습니다.

범주 및 공급자 DropDownLists에 대한 값을 지원 NULL 하려면 를 추가 ListItem해야 합니다. 이 ListItem의 값으로 Text (없음)을 사용하도록 선택했지만 원하는 경우 다른 항목(예: 빈 문자열)으로 변경할 수 있습니다. 마지막으로 DropDownLists AppendDataBoundItemsTrue를 로 설정해야 합니다. 이렇게 하는 것을 잊어버린 경우 DropDownList에 바인딩된 범주 및 공급자는 정적으로 추가 ListItem된 를 덮어씁니다.

이러한 변경 후 DataList EditItemTemplate 의 DropDownLists 태그는 다음과 유사하게 표시됩니다.

<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
    DataTextField="CategoryName" DataValueField="CategoryID" runat="server"
    SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
    DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
    SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>

참고

정적 ListItem s는 Designer 통해 또는 선언적 구문을 통해 직접 DropDownList에 추가할 수 있습니다. 데이터베이스 NULL 값을 나타내는 DropDownList 항목을 추가할 때 선언적 구문을 통해 를 추가 ListItem 해야 합니다. Designer 컬렉션 편집기 사용하는 ListItem 경우 생성된 선언적 구문은 빈 문자열을 할당할 때 설정을 모두 생략 Value 하여 다음과 같은 <asp:ListItem>(None)</asp:ListItem>선언적 태그를 만듭니다. 이로 인해 무해해 보일 수 있지만 누락 Value 으로 인해 DropDownList가 Text 해당 위치에서 속성 값을 사용합니다. 즉, 이 NULLListItem 옵션을 선택하면 값(없음)이 제품 데이터 필드(CategoryID 또는 SupplierID이 자습서에서는 )에 할당되어 예외가 발생합니다. 를 명시적으로 설정 Value=""NULL 하면 가 선택되면 값이 제품 데이터 필드에 NULLListItem 할당됩니다.

잠시 시간을 내어 브라우저를 통해 진행 상황을 봅니다. 제품을 Categories 편집할 때 및 Suppliers DropDownLists 모두 DropDownList 시작 부분에 (없음) 옵션이 있습니다.

범주 및 공급업체 드롭다운 목록에는 (없음) 옵션이 포함됩니다.

그림 10: CategoriesSuppliers DropDownLists에는 (없음) 옵션이 포함되어 있습니다(전체 크기 이미지를 보려면 클릭).

(없음) 옵션을 데이터베이스 NULL 값으로 저장하려면 이벤트 처리기로 UpdateCommand 돌아가야 합니다. 및 변수를 categoryIDValue nullable 정수로 변경하고 DropDownList가 SelectedValue 빈 문자열이 아닌 경우에만 값을 Nothing 할당 supplierIDValue 합니다.

int? categoryIDValue = null;
if (!string.IsNullOrEmpty(categories.SelectedValue))
    categoryIDValue = Convert.ToInt32(categories.SelectedValue);
int? supplierIDValue = null;
if (!string.IsNullOrEmpty(suppliers.SelectedValue))
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);

이 변경으로 사용자가 데이터베이스 값 NothingUpdateProduct 해당하는 드롭다운 목록 중 하나에서 (없음) 옵션을 선택한 경우 값이 BLL 메서드로 NULL 전달됩니다.

요약

이 자습서에서는 TextBox, 두 개의 DropDownList 및 CheckBox와 유효성 검사 컨트롤의 세 가지 다른 입력 웹 컨트롤을 포함하는 보다 복잡한 DataList 편집 인터페이스를 만드는 방법을 알아보았습니다. 편집 인터페이스를 빌드할 때는 사용 중인 웹 컨트롤에 관계없이 단계가 동일합니다. 먼저 DataList에 EditItemTemplate웹 컨트롤을 추가하고, databinding 구문을 사용하여 해당 데이터 필드 값을 적절한 웹 컨트롤 속성으로 할당하고, 이벤트 처리기에서 UpdateCommand 프로그래밍 방식으로 웹 컨트롤 및 해당 속성에 액세스합니다. BLL에 해당 값을 전달합니다.

편집 인터페이스를 만들 때 TextBoxes만 구성하든 다른 웹 컨트롤의 컬렉션으로 구성되든 데이터베이스 NULL 값을 올바르게 처리해야 합니다. 를 계산 NULL 할 때는 편집 인터페이스에 기존 NULL 값을 올바르게 표시할 뿐만 아니라 값을 로 NULL표시하는 방법을 제공해야 합니다. DataLists의 DropDownLists의 경우 일반적으로 속성이 빈 문자열()Value=""로 명시적으로 설정된 정적 ListItemValue 을 추가하고 이벤트 처리기에 코드를 UpdateCommand 약간 추가하여 이 선택되었는지 여부를 NULL``ListItem 확인합니다.

행복한 프로그래밍!

저자 정보

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

특별 감사

이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 데니스 패터슨, 데이비드 수루, 랜디 슈미트였습니다. 예정된 MSDN 문서를 검토하시겠습니까? 그렇다면 에 줄을 놓습니다 mitchell@4GuysFromRolla.com.