데이터 수정 인터페이스 사용자 지정(VB)Customizing the Data Modification Interface (VB)

Scott Mitchellby Scott Mitchell

샘플 앱 다운로드 또는 PDF 다운로드Download Sample App or Download PDF

이 자습서에서는 표준 텍스트 상자 및 CheckBox 컨트롤을 대체 입력 웹 컨트롤로 바꿔서 편집 가능한 GridView의 인터페이스를 사용자 지정 하는 방법에 대해 살펴보겠습니다.In this tutorial we'll look at how to customize the interface of an editable GridView, by replacing the standard TextBox and CheckBox controls with alternative input Web controls.

소개Introduction

GridView 및 DetailsView 컨트롤에서 사용 하는 BoundFields 및 CheckBoxFields는 읽기 전용, 편집 가능 및 삽입 가능 인터페이스를 렌더링 하는 기능 때문에 데이터를 수정 하는 프로세스를 간소화 합니다.The BoundFields and CheckBoxFields used by the GridView and DetailsView controls simplify the process of modifying data due to their ability to render read-only, editable, and insertable interfaces. 이러한 인터페이스는 추가로 선언 태그나 코드를 추가할 필요 없이 렌더링할 수 있습니다.These interfaces can be rendered without the need for adding any additional declarative markup or code. 그러나 BoundField 및 CheckBoxField의 인터페이스에는 실제 시나리오에서 자주 필요한 사용자 지정 가능성 부족 합니다.However, the BoundField and CheckBoxField's interfaces lack the customizability often needed in real-world scenarios. GridView 또는 DetailsView에서 편집 또는 삽입 가능한 인터페이스를 사용자 지정 하려면 Templatefield로 변환를 대신 사용 해야 합니다.In order to customize the editable or insertable interface in a GridView or DetailsView we need to instead use a TemplateField.

이전 자습서 에서는 유효성 검사 웹 컨트롤을 추가 하 여 데이터 수정 인터페이스를 사용자 지정 하는 방법을 살펴보았습니다.In the preceding tutorial we saw how to customize the data modification interfaces by adding validation Web controls. 이 자습서에서는 BoundField 및 CheckBoxField의 표준 TextBox 및 CheckBox 컨트롤을 대체 입력 웹 컨트롤로 대체 하 여 실제 데이터 컬렉션 웹 컨트롤을 사용자 지정 하는 방법을 살펴보겠습니다.In this tutorial we'll look at how to customize the actual data collection Web controls, replacing the BoundField and CheckBoxField's standard TextBox and CheckBox controls with alternative input Web controls. 특히 제품의 이름, 범주, 공급 업체 및 단종 된 상태를 업데이트 하는 데 사용할 수 있는 편집 가능한 GridView를 빌드합니다.In particular, we'll build an editable GridView that allows a product's name, category, supplier, and discontinued status to be updated. 특정 행을 편집할 때 범주 및 공급자 필드는 선택할 수 있는 범주 및 공급자 집합이 포함 된 Dropdownlist로 렌더링 됩니다.When editing a particular row, the category and supplier fields will render as DropDownLists, containing the set of available categories and suppliers to choose from. 또한 CheckBoxField의 기본 확인란을 두 가지 옵션인 "Active" 및 "단종"을 제공 하는 RadioButtonList 컨트롤로 바꿉니다.Furthermore, we'll replace the CheckBoxField's default CheckBox with a RadioButtonList control that offers two options: "Active" and "Discontinued".

GridView의 편집 인터페이스에 Dropdownlist 및 Radiobutton이 포함 되어 있습니다.The GridView's Editing Interface Includes DropDownLists and RadioButtons

그림 1: GridView의 편집 인터페이스에 Dropdownlist 및 radiobutton (전체 크기 이미지를 보려면 클릭)이 포함 되어 있습니다.Figure 1: The GridView's Editing Interface Includes DropDownLists and RadioButtons (Click to view full-size image)

1 단계: 적절 한UpdateProduct오버 로드 만들기Step 1: Creating the AppropriateUpdateProductOverload

이 자습서에서는 제품 이름, 범주, 공급 업체 및 단종 된 상태를 편집할 수 있도록 하는 편집 가능한 GridView를 작성 합니다.In this tutorial we will build an editable GridView that permits editing of a product's name, category, supplier, and discontinued status. 따라서 5 개의 입력 매개 변수를 허용 하는 UpdateProduct 오버 로드 (4 개의 제품 값과 ProductID를 더한 값이 필요 합니다.Therefore, we need an UpdateProduct overload that accepts five input parameters these four product values plus the ProductID. 이전 오버 로드에서와 같이 다음과 같이 합니다.Like in our previous overloads, this one will:

  1. 데이터베이스에서 지정 된 ProductID에 대 한 제품 정보를 검색 합니다.Retrieve the product information from the database for the specified ProductID,
  2. ProductName, CategoryID, SupplierIDDiscontinued 필드를 업데이트 합니다.Update the ProductName, CategoryID, SupplierID, and Discontinued fields, and
  3. TableAdapter의 Update() 메서드를 통해 DAL에 업데이트 요청을 보냅니다.Send the update request to the DAL through the TableAdapter's Update() method.

간단히 하기 위해이 특정 오버 로드의 경우 중단 됨으로 표시 되는 제품이 해당 공급 업체에서 제공 하는 유일한 제품이 아님을 확인 하는 비즈니스 규칙 검사를 생략 했습니다.For brevity, for this particular overload I've omitted the business rule check that ensures a product being marked as discontinued isn't the only product offered by its supplier. 원하는 경우에는 논리를 별도의 메서드에 추가 하는 것이 좋습니다.Feel free to add it in if you prefer, or, ideally, refactor out the logic to a separate method.

다음 코드에서는 ProductsBLL 클래스의 새 UpdateProduct 오버 로드를 보여 줍니다.The following code shows the new UpdateProduct overload in the ProductsBLL class:

<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, False)>
Public Function UpdateProduct(
    ByVal productName As String, ByVal categoryID As Nullable(Of Integer), 
    ByVal supplierID As Nullable(Of Integer), ByVal discontinued As Boolean, 
    ByVal productID As Integer)
    As Boolean
    Dim products As Northwind.ProductsDataTable = Adapter.GetProductByProductID(productID)
    If products.Count = 0 Then
        Return False
    End If
    Dim product As Northwind.ProductsRow = products(0)
    product.ProductName = productName
    If Not supplierID.HasValue Then
        product.SetSupplierIDNull()
    Else
        product.SupplierID = supplierID.Value
    End If
    If Not categoryID.HasValue Then
        product.SetCategoryIDNull()
    Else
        product.CategoryID = categoryID.Value
    End If
    product.Discontinued = discontinued
    Dim rowsAffected As Integer = Adapter.Update(product)
    Return rowsAffected = 1
End Function

2 단계: 편집 가능한 GridView를 만들고 있습니다.Step 2: Crafting the Editable GridView

UpdateProduct 오버 로드를 추가 하면 편집 가능한 GridView를 만들 준비가 되었습니다.With the UpdateProduct overload added, we're ready to create our editable GridView. EditInsertDelete 폴더에서 CustomizedUI.aspx 페이지를 열고 디자이너에 GridView 컨트롤을 추가 합니다.Open the CustomizedUI.aspx page in the EditInsertDelete folder and add a GridView control to the Designer. 다음으로 GridView의 스마트 태그에서 새 ObjectDataSource를 만듭니다.Next, create a new ObjectDataSource from the GridView's smart tag. ProductBLL 클래스의 GetProducts() 메서드를 통해 제품 정보를 검색 하 고 방금 만든 UpdateProduct 오버 로드를 사용 하 여 제품 데이터를 업데이트 하도록 ObjectDataSource를 구성 합니다.Configure the ObjectDataSource to retrieve product information via the ProductBLL class's GetProducts() method and to update product data using the UpdateProduct overload we just created. 삽입 및 삭제 탭의 드롭다운 목록에서 (없음)을 선택 합니다.From the INSERT and DELETE tabs, select (None) from the drop-down lists.

위에서 만든 UpdateProduct 오버 로드를 사용 하도록 ObjectDataSource를 구성 Configure the ObjectDataSource to Use the UpdateProduct Overload Just Created

그림 2: 막 만든 UpdateProduct 오버 로드를 사용 하도록 ObjectDataSource 구성 (전체 크기 이미지를 보려면 클릭)Figure 2: Configure the ObjectDataSource to Use the UpdateProduct Overload Just Created (Click to view full-size image)

데이터 수정 자습서에서 살펴본 것 처럼 Visual Studio에서 만든 ObjectDataSource의 선언 구문은 original_{0}OldValuesParameterFormatString 속성을 할당 합니다.As we've seen throughout the data modification tutorials, the declarative syntax for the ObjectDataSource created by Visual Studio assigns the OldValuesParameterFormatString property to original_{0}. 물론 원래 ProductID 값이 전달 될 것으로 간주 되기 때문에 비즈니스 논리 계층에서는 작동 하지 않습니다.This, of course, won't work with our Business Logic Layer since our methods don't expect the original ProductID value to be passed in. 따라서 이전 자습서에서 수행한 것 처럼 잠시 후에 선언적 구문에서이 속성 할당을 제거 하거나 대신이 속성의 값을 {0}로 설정 합니다.Therefore, as we've done in previous tutorials, take a moment to remove this property assignment from the declarative syntax or, instead, set this property's value to {0}.

이 변경 후 ObjectDataSource의 선언 태그는 다음과 같습니다.After this change, the ObjectDataSource's declarative markup should look like the following:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

OldValuesParameterFormatString 속성이 제거 되었으며 UpdateProduct 오버 로드에 필요한 각 입력 매개 변수에 대 한 UpdateParameters 컬렉션에 Parameter 있는지 확인 합니다.Note that the OldValuesParameterFormatString property has been removed and that there is a Parameter in the UpdateParameters collection for each of the input parameters expected by our UpdateProduct overload.

ObjectDataSource는 제품 값의 하위 집합만 업데이트 하도록 구성 되지만 현재 GridView에는 모든 product 필드가 표시 됩니다.While the ObjectDataSource is configured to update only a subset of product values, the GridView currently shows all of the product fields. 잠시 후 다음을 수행 하도록 GridView를 편집 합니다.Take a moment to edit the GridView so that:

  • ProductName, SupplierName, CategoryName BoundFields 및 Discontinued CheckBoxField만 포함 됩니다.It only includes the ProductName, SupplierName, CategoryName BoundFields and the Discontinued CheckBoxField
  • CategoryNameSupplierName 필드가 Discontinued CheckBoxField의 왼쪽에 표시 됩니다.The CategoryName and SupplierName fields to appear before (to the left of) the Discontinued CheckBoxField
  • CategoryNameSupplierName BoundFields ' HeaderText 속성은 각각 "Category" 및 "공급자"로 설정 됩니다.The CategoryName and SupplierName BoundFields' HeaderText property is set to "Category" and "Supplier", respectively
  • 편집 지원이 사용 하도록 설정 되어 있습니다. GridView의 스마트 태그에서 편집 사용 확인란을 선택 합니다.Editing support is enabled (check the Enable Editing checkbox in the GridView's smart tag)

이러한 변경 후에 디자이너는 아래와 같은 GridView의 선언 구문을 사용 하 여 그림 3과 유사 하 게 표시 됩니다.After these changes, the Designer will look similar to Figure 3, with the GridView's declarative syntax shown below.

GridView에서 불필요 한 필드를 제거 합니다.Remove the Unneeded Fields from the GridView

그림 3: GridView에서 불필요 한 필드 제거 (전체 크기 이미지를 보려면 클릭)Figure 3: Remove the Unneeded Fields from the GridView (Click to view full-size image)

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:BoundField DataField="ProductName"
           HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
           ReadOnly="True"
           SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier"
           ReadOnly="True"
           SortExpression="SupplierName" />
        <asp:CheckBoxField DataField="Discontinued"
           HeaderText="Discontinued" SortExpression="Discontinued" />
    </Columns>
</asp:GridView>

이 시점에서 GridView의 읽기 전용 동작이 완료 됩니다.At this point the GridView's read-only behavior is complete. 데이터를 볼 때 각 제품은 GridView의 행으로 렌더링 되어 제품의 이름, 범주, 공급 업체 및 단종 상태를 표시 합니다.When viewing the data, each product is rendered as a row in the GridView, showing the product's name, category, supplier, and discontinued status.

GridView의 읽기 전용 인터페이스가 완료 The GridView's Read-Only Interface is Complete

그림 4: GridView의 읽기 전용 인터페이스가 완료 되었습니다 (전체 크기 이미지를 보려면 클릭).Figure 4: The GridView's Read-Only Interface is Complete (Click to view full-size image)

Note

데이터 삽입, 업데이트 및 삭제 자습서의 개요에서 설명한 것 처럼 GridView의 뷰 상태를 사용 하도록 설정 하는 것이 매우 중요 합니다 (기본 동작).As discussed in An Overview of Inserting, Updating, and Deleting Data tutorial, it is vitally important that the GridView s view state be enabled (the default behavior). GridView s EnableViewState 속성을 false로 설정 하면 동시 사용자가 실수로 레코드를 삭제 하거나 편집 하는 위험을 발생 시킬 수 있습니다.If you set the GridView s EnableViewState property to false, you run the risk of having concurrent users unintentionally deleting or editing records. 자세한 내용은 경고: 편집 및/또는 삭제를 지원 하 고 해당 뷰 상태를 사용할 수 없는 ASP.NET 2.0 gridviews/DetailsView/FormViews의 동시성 문제 를 참조 하세요.See WARNING: Concurrency Issue with ASP.NET 2.0 GridViews/DetailsView/FormViews that Support Editing and/or Deleting and Whose View State is Disabled for more information.

3 단계: 범주 및 공급자 편집 인터페이스에 대 한 DropDownList 사용Step 3: Using a DropDownList for the Category and Supplier Editing Interfaces

ProductsRow 개체에는 SupplierName 데이터베이스 테이블의 실제 외래 키 ID 값과 ProductsName 테이블의 해당 Categories 값을 제공 하는 CategoryID, CategoryName, SupplierIDSuppliers 속성이 포함 되어 있습니다.Recall that the ProductsRow object contains CategoryID, CategoryName, SupplierID, and SupplierName properties, which provide the actual foreign-key ID values in the Products database table and the corresponding Name values in the Categories and Suppliers tables. ProductRowCategoryIDSupplierID은 모두 읽고 쓸 수 있으며, CategoryNameSupplierName 속성은 읽기 전용으로 표시 됩니다.The ProductRow's CategoryID and SupplierID can both be read from and written to, while the CategoryName and SupplierName properties are marked read-only.

CategoryNameSupplierName 속성의 읽기 전용 상태로 인해 해당 BoundFields는 ReadOnly 속성을 True로 설정 하 여 행을 편집할 때 이러한 값이 수정 되지 않도록 합니다.Due to the read-only status of the CategoryName and SupplierName properties, the corresponding BoundFields have had their ReadOnly property set to True, preventing these values from being modified when a row is edited. ReadOnly 속성을 False로 설정 하 고, CategoryName를 렌더링 하 고, 편집 하는 동안 텍스트 상자를 SupplierName 하는 경우 이러한 접근 방식은 UpdateProductCategoryName 입력을 사용 하는 SupplierName 오버 로드가 없으므로 사용자가 제품을 업데이트 하려고 할 때 예외를 발생 시킵니다.While we can set the ReadOnly property to False, rendering the CategoryName and SupplierName BoundFields as TextBoxes during editing, such an approach will result in an exception when the user attempts to update the product since there is no UpdateProduct overload that takes in CategoryName and SupplierName inputs. 실제로 다음과 같은 두 가지 이유로 이러한 오버 로드를 만들지 않으려고 합니다.In fact, we don't want to create such an overload for two reasons:

  • Products 테이블에는 SupplierName 또는 CategoryName 필드가 없지만 SupplierIDCategoryID는 있습니다.The Products table doesn't have SupplierName or CategoryName fields, but SupplierID and CategoryID. 따라서 메서드에서 조회 테이블의 값이 아닌 이러한 특정 ID 값을 전달 하려고 합니다.Therefore, we want our method to be passed these particular ID values, not their lookup tables' values.
  • 사용자가 사용 가능한 범주와 공급 업체 및 올바른 철자를 알아야 하므로 공급자 또는 범주의 이름을 입력 하도록 요구 하는 것이 이상적입니다.Requiring the user to type in the name of the supplier or category is less than ideal, as it requires the user to know the available categories and suppliers and their correct spellings.

공급자 및 범주 필드에는 읽기 전용 모드 (현재는 그대로) 및 편집할 때 적용 가능한 옵션의 드롭다운 목록에 있는 범주 및 공급자 이름이 표시 됩니다.The supplier and category fields should display the category and suppliers' names when in read-only mode (as it does now) and a drop-down list of applicable options when being edited. 최종 사용자는 드롭다운 목록을 사용 하 여 선택할 수 있는 범주와 공급자를 빠르게 확인 하 고 더 쉽게 선택할 수 있습니다.Using a drop-down list, the end user can quickly see what categories and suppliers are available to choose among and can more easily make their selection.

이 동작을 제공 하려면 SupplierNameCategoryName BoundFields를 템플릿 필드로 변환 해야 합니다 .이 필드는 ItemTemplate SupplierNameCategoryName 값을 내보내고 해당 EditItemTemplate에서 DropDownList 컨트롤을 사용 하 여 사용 가능한 범주 및 공급자를 나열 합니다.To provide this behavior, we need to convert the SupplierName and CategoryName BoundFields into TemplateFields whose ItemTemplate emits the SupplierName and CategoryName values and whose EditItemTemplate uses a DropDownList control to list the available categories and suppliers.

CategoriesSuppliersDropdownlist 추가Adding theCategoriesandSuppliersDropDownLists

먼저 SupplierName를 변환 하 고 GridView의 스마트 태그에서 열 편집 링크를 클릭 하 여 BoundFields를 템플릿 필드로 CategoryName 합니다. 왼쪽 아래에 있는 목록에서 BoundField를 선택 합니다. "이 필드를 Templatefield로 변환으로 변환" 링크를 클릭 합니다.Start by converting the SupplierName and CategoryName BoundFields into TemplateFields by: clicking on the Edit Columns link from the GridView's smart tag; selecting the BoundField from the list in the lower left; and clicking the "Convert this field into a TemplateField" link. 변환 프로세스는 아래 선언 구문에 나와 있는 것 처럼 ItemTemplateEditItemTemplate를 모두 사용 하 여 Templatefield로 변환를 만듭니다.The conversion process will create a TemplateField with both an ItemTemplate and an EditItemTemplate, as shown in the declarative syntax below:

<asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
    <EditItemTemplate>
        <asp:Label ID="Label1" runat="server"
          Text='<%# Eval("CategoryName") %>'></asp:Label>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label1" runat="server"
          Text='<%# Bind("CategoryName") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

BoundField는 읽기 전용으로 표시 되어 있으므로 ItemTemplateEditItemTemplate에는 Text 속성이 적용 되는 데이터 필드 (CategoryName, 위의 구문)에 바인딩되는 Label 웹 컨트롤이 포함 되어 있습니다.Since the BoundField was marked as read-only, both the ItemTemplate and EditItemTemplate contain a Label Web control whose Text property is bound to the applicable data field (CategoryName, in the syntax above). 레이블 웹 컨트롤을 DropDownList 컨트롤로 바꿔서 EditItemTemplate를 수정 해야 합니다.We need to modify the EditItemTemplate, replacing the Label Web control with a DropDownList control.

이전 자습서에서 살펴본 것 처럼 디자이너를 통해 또는 선언적 구문에서 직접 템플릿을 편집할 수 있습니다.As we've seen in previous tutorials, the template can be edited through the Designer or directly from the declarative syntax. 디자이너를 통해 편집 하려면 GridView의 스마트 태그에서 템플릿 편집 링크를 클릭 하 고 범주 필드의 EditItemTemplate사용 하도록 선택 합니다.To edit it through the Designer, click on the Edit Templates link from the GridView's smart tag and choose to work with the Category field's EditItemTemplate. 레이블 웹 컨트롤을 제거 하 고 dropdownlist 컨트롤로 바꿔서 DropDownList의 ID 속성을 Categories로 설정 합니다.Remove the Label Web control and replace it with a DropDownList control, setting the DropDownList's ID property to Categories.

텍스트 상자를 제거 하 고 EditItemTemplate에 DropDownList을 추가 Remove the TexBox and Add a DropDownList to the EditItemTemplate

그림 5: 텍스트 상자를 제거 하 고 EditItemTemplate에 DropDownList 추가 (전체 크기 이미지를 보려면 클릭)Figure 5: Remove the TexBox and Add a DropDownList to the EditItemTemplate (Click to view full-size image)

다음으로 DropDownList를 사용 가능한 범주로 채워야 합니다.We next need to populate the DropDownList with the available categories. DropDownList의 스마트 태그에서 데이터 소스 선택 링크를 클릭 하 고 옵트인을 선택 하 여 CategoriesDataSource라는 새 ObjectDataSource를 만듭니다.Click on the Choose Data Source link from the DropDownList's smart tag and opt to create a new ObjectDataSource named CategoriesDataSource.

범주 Datasource 라는 새 ObjectDataSource 컨트롤을 만듭니다.Create a New ObjectDataSource Control Named CategoriesDataSource

그림 6: CategoriesDataSource 이라는 새 ObjectDataSource 컨트롤 만들기 (전체 크기 이미지를 보려면 클릭)Figure 6: Create a New ObjectDataSource Control Named CategoriesDataSource (Click to view full-size image)

이 ObjectDataSource가 모든 범주를 반환 하도록 하려면 CategoriesBLL 클래스의 GetCategories() 메서드에 바인딩합니다.To have this ObjectDataSource return all of the categories, bind it to the CategoriesBLL class's GetCategories() method.

ObjectDataSource를 범주 Bll의 GetCategories () 메서드에 바인딩합니다.Bind the ObjectDataSource to the CategoriesBLL's GetCategories() Method

그림 7: ObjectDataSource를 CategoriesBLLGetCategories() 메서드에 바인딩 (전체 크기 이미지를 보려면 클릭)Figure 7: Bind the ObjectDataSource to the CategoriesBLL's GetCategories() Method (Click to view full-size image)

마지막으로 값으로 사용 되는 CategoryID 필드를 사용 하 여 CategoryName 필드가 각 DropDownList ListItem에 표시 되도록 DropDownList의 설정을 구성 합니다.Finally, configure the DropDownList's settings such that the CategoryName field is displayed in each DropDownList ListItem with the CategoryID field used as the value.

범주 필드와 값으로 사용 되는 CategoryID를 표시 Have the CategoryName Field Displayed and the CategoryID Used as the Value

그림 8: CategoryName 필드가 표시 되 고 CategoryID 값으로 사용 (전체 크기 이미지를 보려면 클릭)Figure 8: Have the CategoryName Field Displayed and the CategoryID Used as the Value (Click to view full-size image)

이러한 변경을 수행한 후 CategoryName Templatefield로 변환의 EditItemTemplate에 대 한 선언적 태그는 DropDownList 및 ObjectDataSource를 모두 포함 합니다.After making these changes the declarative markup for the EditItemTemplate in the CategoryName TemplateField will include both a DropDownList and an ObjectDataSource:

<asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
    <EditItemTemplate>
        <asp:DropDownList ID="Categories" runat="server"
          DataSourceID="CategoriesDataSource"
          DataTextField="CategoryName" DataValueField="CategoryID">
        </asp:DropDownList>
        <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
            OldValuesParameterFormatString="original_{0}"
            SelectMethod="GetCategories" TypeName="CategoriesBLL">
        </asp:ObjectDataSource>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label1" runat="server"
          Text='<%# Bind("CategoryName") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

Note

EditItemTemplate에서 DropDownList의 뷰 상태를 사용 하도록 설정 해야 합니다.The DropDownList in the EditItemTemplate must have its view state enabled. 곧 DropDownList의 선언적 구문에 데이터 바인딩 구문을 추가 하 고 Eval() Bind()와 같은 데이터 바인딩 명령을 추가 하 여 뷰 상태를 사용 하는 컨트롤에만 나타날 수 있습니다.We will soon add databinding syntax to the DropDownList's declarative syntax and databinding commands like Eval() and Bind() can only appear in controls whose view state is enabled.

이러한 단계를 반복 하 여 SupplierName Templatefield로 변환의 EditItemTemplateSuppliers 라는 DropDownList을 추가 합니다.Repeat these steps to add a DropDownList named Suppliers to the SupplierName TemplateField's EditItemTemplate. 이렇게 하려면 EditItemTemplate에 DropDownList을 추가 하 고 다른 ObjectDataSource를 만들어야 합니다.This will involve adding a DropDownList to the EditItemTemplate and creating another ObjectDataSource. 그러나 Suppliers DropDownList의 ObjectDataSource는 SuppliersBLL 클래스의 GetSuppliers() 메서드를 호출 하도록 구성 되어야 합니다.The Suppliers DropDownList's ObjectDataSource, however, should be configured to invoke the SuppliersBLL class's GetSuppliers() method. 또한 Suppliers DropDownList을 구성 하 여 CompanyName 필드를 표시 하 고 SupplierID 필드를 ListItem s에 대 한 값으로 사용 합니다.Additionally, configure the Suppliers DropDownList to display the CompanyName field and use the SupplierID field as the value for its ListItem s.

EditItemTemplate s에 Dropdownlist를 추가한 후 브라우저에서 페이지를 로드 하 고 Chef Anton의 Cajun Seasoning product에 대 한 편집 단추를 클릭 합니다.After adding the DropDownLists to the two EditItemTemplate s, load the page in a browser and click the Edit button for the Chef Anton's Cajun Seasoning product. 그림 9에 표시 된 것 처럼 제품의 범주 및 공급자 열은 선택할 수 있는 범주 및 공급자가 포함 된 드롭다운 목록으로 렌더링 됩니다.As Figure 9 shows, the product's category and supplier columns are rendered as drop-down lists containing the available categories and suppliers to choose from. 그러나 Chef Anton의 Cajun Seasoning가 새 Orleans Cajun Delights에서 제공 되는 경우에도 두 드롭다운 목록의 첫 번째 항목이 기본적으로 선택 되어 있습니다 (범주의 음료 및 Exotic Liquids).However, note that the first items in both drop-down lists are selected by default (Beverages for the category and Exotic Liquids as the supplier), even though Chef Anton's Cajun Seasoning is a Condiment supplied by New Orleans Cajun Delights.

드롭다운 목록의 첫 번째 항목을 기본적으로 선택 됩니다.The First Item in the Drop-Down Lists is Selected by Default

그림 9: 드롭다운 목록의 첫 번째 항목이 기본적으로 선택 되어 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 9: The First Item in the Drop-Down Lists is Selected by Default (Click to view full-size image)

또한 업데이트를 클릭 하면 제품의 CategoryIDSupplierID 값이 NULL으로 설정 된 것을 알 수 있습니다.Furthermore, if you click Update, you'll find that the product's CategoryID and SupplierID values are set to NULL. 이러한 원치 않는 동작은 EditItemTemplate s의 Dropdownlist가 기본 제품 데이터의 데이터 필드에 바인딩되지 않기 때문에 발생 합니다.Both of these undesired behaviors are caused because the DropDownLists in the EditItemTemplate s are not bound to any data fields from the underlying product data.

CategoryIDSupplierID데이터 필드에 Dropdownlist 바인딩Binding the DropDownLists to theCategoryIDandSupplierIDData Fields

편집 된 제품의 범주 및 공급자 드롭다운 목록을 적절 한 값으로 설정 하 고 업데이트를 클릭 했을 때 이러한 값이 BLL의 UpdateProduct 메서드로 다시 전송 되도록 하려면 Dropdownlist ' SelectedValue 속성을 CategoryID에 바인딩하고 양방향 데이터 바인딩을 사용 하 여 데이터 필드를 SupplierID 해야 합니다.In order to have the edited product's category and supplier drop-down lists set to the appropriate values and to have these values sent back to the BLL's UpdateProduct method upon clicking Update, we need to bind the DropDownLists' SelectedValue properties to the CategoryID and SupplierID data fields using two-way databinding. Categories DropDownList를 사용 하 여이를 수행 하려면 선언적 구문에 SelectedValue='<%# Bind("CategoryID") %>'를 직접 추가할 수 있습니다.To accomplish this with the Categories DropDownList, you can add SelectedValue='<%# Bind("CategoryID") %>' directly to the declarative syntax.

또는 디자이너를 통해 템플릿을 편집 하 고 DropDownList의 스마트 태그에서 데이터 바인딩 편집 링크를 클릭 하 여 DropDownList의 데이터 집합을 설정할 수 있습니다.Alternatively, you can set the DropDownList's databindings by editing the template through the Designer and clicking the Edit DataBindings link from the DropDownList's smart tag. 그런 다음 양방향 데이터 바인딩을 사용 하 여 SelectedValue 속성이 CategoryID 필드에 바인딩되어야 함을 표시 합니다 (그림 10 참조).Next, indicate that the SelectedValue property should be bound to the CategoryID field using two-way databinding (see Figure 10). 선언적 또는 디자이너 프로세스를 반복 하 여 SupplierID 데이터 필드를 Suppliers DropDownList에 바인딩합니다.Repeat either the declarative or Designer process to bind the SupplierID data field to the Suppliers DropDownList.

양방향 데이터 바인딩을 사용 하 여 CategoryID를 DropDownList의 SelectedValue 속성에 바인딩합니다.Bind the CategoryID to the DropDownList's SelectedValue Property Using Two-Way Databinding

그림 10: 양방향 데이터 바인딩을 사용 하 여 CategoryID를 DropDownList의 SelectedValue 속성에 바인딩 (전체 크기 이미지를 보려면 클릭)Figure 10: Bind the CategoryID to the DropDownList's SelectedValue Property Using Two-Way Databinding (Click to view full-size image)

바인딩이 두 Dropdownlist의 SelectedValue 속성에 적용 된 후에는 편집 된 제품의 범주 및 공급자 열이 기본적으로 현재 제품의 값으로 바뀝니다.Once the bindings have been applied to the SelectedValue properties of the two DropDownLists, the edited product's category and supplier columns will default to the current product's values. 업데이트를 클릭 하면 선택한 드롭다운 목록 항목의 CategoryIDSupplierID 값이 UpdateProduct 메서드에 전달 됩니다.Upon clicking Update, the CategoryID and SupplierID values of the selected drop-down list item will be passed to the UpdateProduct method. 그림 11에서는 데이터 바인딩 문이 추가 된 후의 자습서를 보여 줍니다. Chef Anton의 Cajun Seasoning에 대해 선택한 드롭다운 목록 항목은 제대로 작동 하 고 새로운 Orleans Cajun Delights에 대 한 정보를 확인 합니다.Figure 11 shows the tutorial after the databinding statements have been added; note how the selected drop-down list items for Chef Anton's Cajun Seasoning are correctly Condiment and New Orleans Cajun Delights.

편집 된 제품의 현재 범주 및 공급자 값이 기본적으로 선택 됩니다.The Edited Product's Current Category and Supplier Values are Selected by Default

그림 11: 편집 된 제품의 현재 범주 및 공급자 값이 기본적으로 선택 되어 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 11: The Edited Product's Current Category and Supplier Values are Selected by Default (Click to view full-size image)

NULL값 처리HandlingNULLValues

Products 테이블의 CategoryIDSupplierID 열을 NULL수 있지만 EditItemTemplate의 Dropdownlist에는 NULL 값을 나타내는 목록 항목이 포함 되지 않습니다.The CategoryID and SupplierID columns in the Products table can be NULL, yet the DropDownLists in the EditItemTemplate s don't include a list item to represent a NULL value. 이 경우 두 가지 결과가 발생 합니다.This has two consequences:

  • 사용자는 인터페이스를 사용 하 여 제품의 범주 또는 공급자를NULL 이외의 값에서 NULL로 변경할 수 없습니다.User cannot use our interface to change a product's category or supplier from a non-NULL value to a NULL one
  • 제품에 NULL CategoryID 또는 SupplierID있는 경우 편집 단추를 클릭 하면 예외가 발생 합니다.If a product has a NULL CategoryID or SupplierID, clicking the Edit button will result in an exception. 이는 Bind() 문의 CategoryID (또는 SupplierID)에서 반환 된 NULL 값이 DropDownList의 값에 매핑되지 않기 때문입니다. (SelectedValue 속성이 목록 항목의 컬렉션에 없는 값으로 설정 된 경우에는 dropdownlist에서 예외가 throw 됩니다.)This is because the NULL value returned by CategoryID (or SupplierID) in the Bind() statement does not map to a value in the DropDownList (the DropDownList throws an exception when its SelectedValue property is set to a value not in its collection of list items).

NULL CategoryIDSupplierID 값을 지원 하기 위해 각 DropDownList에 다른 ListItem를 추가 하 여 NULL 값을 표시 해야 합니다.In order to support NULL CategoryID and SupplierID values, we need to add another ListItem to each DropDownList to represent the NULL value. DropDownList 자습서를 사용 하 여 마스터/세부 정보 필터링 에서 dropdownlist의 AppendDataBoundItems 속성을 True로 설정 하 고 추가 ListItem를 수동으로 추가 하는 것과 관련 된 데이터 바인딩된 DropDownList에 추가 ListItem를 추가 하는 방법을 살펴보았습니다.In the Master/Detail Filtering With a DropDownList tutorial, we saw how to add an additional ListItem to a databound DropDownList, which involved setting the DropDownList's AppendDataBoundItems property to True and manually adding the additional ListItem. 그러나 이전 자습서에서는 -1Value를 사용 하 여 ListItem를 추가 했습니다.In that previous tutorial, however, we added a ListItem with a Value of -1. 그러나 ASP.NET의 데이터 바인딩 논리는 빈 문자열을 NULL 값으로 자동으로 변환 하 고 그 반대의 경우도 마찬가지입니다.The databinding logic in ASP.NET, however, will automatically convert a blank string to a NULL value and vice-a-versa. 따라서이 자습서에서는 ListItemValue를 빈 문자열로 만들려고 합니다.Therefore, for this tutorial we want the ListItem's Value to be an empty string.

Dropdownlist ' AppendDataBoundItems 속성을 True으로 설정 하 여 시작 합니다.Start by setting both DropDownLists' AppendDataBoundItems property to True. 다음으로, 다음 <asp:ListItem> 요소를 각 DropDownList에 추가 하 여 선언적 태그가 표시 되도록 NULL ListItem를 추가 합니다.Next, add the NULL ListItem by adding the following <asp:ListItem> element to each DropDownList so that the declarative markup looks like:

<asp:DropDownList ID="Categories" runat="server"
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
    AppendDataBoundItems="True">
    <asp:ListItem Value="">(None)</asp:ListItem>
</asp:DropDownList>

ListItem에 대 한 텍스트 값으로 "(None)"을 사용 하기로 선택 했지만 원하는 경우 빈 문자열을 사용 하도록 변경할 수도 있습니다.I've chosen to use "(None)" as the Text value for this ListItem, but you can change it to also be a blank string if you'd like.

Note

DropDownList 자습서를 사용 하 여 마스터/세부 정보 필터링 에서 살펴본 것 처럼 속성 창에서 dropdownlist의 Items 속성을 클릭 하 여 디자이너를 통해 ListItem를 dropdownlist에 추가할 수 있습니다 (ListItem 컬렉션 편집기가 표시 됨).As we saw in the Master/Detail Filtering With a DropDownList tutorial, ListItem s can be added to a DropDownList through the Designer by clicking on the DropDownList's Items property in the Properties window (which will display the ListItem Collection Editor). 그러나 선언적 구문을 통해이 자습서에 대 한 NULL ListItem를 추가 해야 합니다.However, be sure to add the NULL ListItem for this tutorial through the declarative syntax. ListItem 컬렉션 편집기를 사용 하는 경우 생성 된 선언적 구문은 빈 문자열이 할당 될 때 Value 설정을 완전히 생략 하 고 <asp:ListItem>(None)</asp:ListItem>와 같은 선언 태그를 만듭니다.If you use the ListItem Collection Editor, the generated declarative syntax will omit the Value setting altogether when assigned a blank string, creating declarative markup like: <asp:ListItem>(None)</asp:ListItem>. 이는 무해 한 것 처럼 보일 수 있지만, 값이 누락 되 면 DropDownList은 대신 Text 속성 값을 사용 합니다.While this may look harmless, the missing Value causes the DropDownList to use the Text property value in its place. 즉,이 NULL ListItem를 선택 하면 CategoryID에 "(없음)" 값이 할당 되어 예외가 발생 합니다.That means that if this NULL ListItem is selected, the value "(None)" will be attempted to be assigned to the CategoryID, which will result in an exception. Value=""를 명시적으로 설정 하 여 NULL ListItem를 선택 하면 CategoryIDNULL 값이 할당 됩니다.By explicitly setting Value="", a NULL value will be assigned to CategoryID when the NULL ListItem is selected.

Suppliers DropDownList에 대해 이러한 단계를 반복 합니다.Repeat these steps for the Suppliers DropDownList.

이 추가 ListItem를 사용 하면 그림 12와 같이 편집 인터페이스에서 제품의 CategoryIDSupplierID 필드에 NULL 값을 할당할 수 있습니다.With this additional ListItem, the editing interface can now assign NULL values to a Product's CategoryID and SupplierID fields, as shown in Figure 12.

제품의 범주 또는 공급 업체에 NULL 값을 할당 하려면 (없음)을 선택 .Choose (None) to Assign a NULL Value for a Product's Category or Supplier

그림 12: (없음)을 선택 하 여 제품의 범주 또는 공급 업체에 대 한 NULL 값 할당 (전체 크기 이미지를 보려면 클릭)Figure 12: Choose (None) to Assign a NULL Value for a Product's Category or Supplier (Click to view full-size image)

4 단계: 단종 된 상태에 대해 Radiobutton 사용Step 4: Using RadioButtons for the Discontinued Status

현재 제품의 Discontinued 데이터 필드는 CheckBoxField를 사용 하 여 표현 됩니다 .이 필드는 편집 중인 행에 대해 읽기 전용 행 및 사용 확인란을 사용 하지 않도록 설정 된 확인란을 렌더링 합니다.Currently the products' Discontinued data field is expressed using a CheckBoxField, which renders a disabled checkbox for the read-only rows and an enabled checkbox for the row being edited. 이 사용자 인터페이스를 사용 하는 것이 적합할 수 있지만 필요한 경우 Templatefield로 변환를 사용 하 여 사용자 지정할 수 있습니다.While this user interface is often suitable, we can customize it if needed using a TemplateField. 이 자습서에서는 사용자가 제품의 Discontinued 값을 지정할 수 있는 두 가지 옵션 "활성" 및 "중단"이 있는 RadioButtonList 컨트롤을 사용 하는 Templatefield로 변환로 CheckBoxField를 변경 하겠습니다.For this tutorial, let's change the CheckBoxField into a TemplateField that uses a RadioButtonList control with two options "Active" and "Discontinued" from which the user can specify the product's Discontinued value.

Discontinued CheckBoxField를 Templatefield로 변환로 변환 하 여 시작 합니다. 그러면 ItemTemplateEditItemTemplate를 사용 하 여 Templatefield로 변환을 만듭니다.Start by converting the Discontinued CheckBoxField into a TemplateField, which will create a TemplateField with an ItemTemplate and EditItemTemplate. 두 템플릿에는 모두 Discontinued 데이터 필드에 바인딩된 Checked 속성이 있는 확인란이 포함 되어 있으며, 두 가지 사이의 유일한 차이점은 ItemTemplate의 CheckBox Enabled 속성이 False로 설정 된다는 것입니다.Both templates include a CheckBox with its Checked property bound to the Discontinued data field, the only difference between the two being that the ItemTemplate's CheckBox's Enabled property is set to False.

ItemTemplateEditItemTemplate의 확인란을 모두 RadioButtonList 컨트롤을 사용 하 여 RadioButtonLists ' ID 속성을 DiscontinuedChoice로 설정 합니다.Replace the CheckBox in both the ItemTemplate and EditItemTemplate with a RadioButtonList control, setting both RadioButtonLists' ID properties to DiscontinuedChoice. 다음으로 RadioButtonLists에 각각 "False" 값을 가진 "활성" 이라는 두 개의 라디오 단추와 "True" 값을 갖는 "단종" 레이블이 지정 된 라디오 단추가 각각 하나씩 포함 되어야 함을 표시 합니다.Next, indicate that the RadioButtonLists should each contain two radio buttons, one labeled "Active" with a value of "False" and one labeled "Discontinued" with a value of "True". 이를 위해 선언적 구문을 통해에 <asp:ListItem> 요소를 직접 입력 하거나 디자이너에서 ListItem 컬렉션 편집기를 사용할 수 있습니다.To accomplish this you can either enter the <asp:ListItem> elements in directly through the declarative syntax or use the ListItem Collection Editor from the Designer. 그림 13에서는 두 개의 라디오 단추 옵션이 지정 된 후 ListItem 컬렉션 편집기를 보여 줍니다.Figure 13 shows the ListItem Collection Editor after the two radio button options have been specified.

RadioButtonList에 활성 및 지원 되지 않는 옵션을 추가 Add Active and Discontinued Options to the RadioButtonList

그림 13: RadioButtonList에 활성 및 중단 된 옵션 추가 (전체 크기 이미지를 보려면 클릭)Figure 13: Add Active and Discontinued Options to the RadioButtonList (Click to view full-size image)

ItemTemplate의 RadioButtonList를 편집할 수 없으므로 Enabled 속성을 False로 설정 하 여 Enabled 속성을 True의 RadioButtonList에 대 한 EditItemTemplate(기본값)로 둡니다.Since the RadioButtonList in the ItemTemplate shouldn't be editable, set its Enabled property to False, leaving the Enabled property to True (the default) for the RadioButtonList in the EditItemTemplate. 이렇게 하면 편집 되지 않은 행의 라디오 단추가 읽기 전용으로 설정 되지만 사용자가 편집 된 행의 RadioButton 값을 변경할 수 있습니다.This will make the radio buttons in the non-edited row as read-only, but will allow the user to change the RadioButton values for the edited row.

제품의 Discontinued 데이터 필드에 따라 적절 한 라디오 단추가 선택 되도록 RadioButtonList 컨트롤의 SelectedValue 속성을 할당 해야 합니다.We still need to assign the RadioButtonList controls' SelectedValue properties so that the appropriate radio button is selected based upon the product's Discontinued data field. 이 자습서의 앞부분에서 살펴본 Dropdownlist와 마찬가지로이 데이터 바인딩 구문은 선언적 태그에 직접 추가 하거나 RadioButtonLists ' 스마트 태그의 데이터 바인딩 편집 링크를 통해 추가할 수 있습니다.As with the DropDownLists examined earlier in this tutorial, this databinding syntax can either be added directly into the declarative markup or through the Edit DataBindings link in the RadioButtonLists' smart tags.

두 RadioButtonLists를 추가 하 고 구성 하 고 나면 Discontinued Templatefield로 변환의 선언 태그는 다음과 같습니다.After adding the two RadioButtonLists and configuring them, the Discontinued TemplateField's declarative markup should look like:

<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
    <ItemTemplate>
        <asp:RadioButtonList ID="DiscontinuedChoice" runat="server"
          Enabled="False" SelectedValue='<%# Bind("Discontinued") %>'>
            <asp:ListItem Value="False">Active</asp:ListItem>
            <asp:ListItem Value="True">Discontinued</asp:ListItem>
        </asp:RadioButtonList>
    </ItemTemplate>
    <EditItemTemplate>
        <asp:RadioButtonList ID="DiscontinuedChoice" runat="server"
            SelectedValue='<%# Bind("Discontinued") %>'>
            <asp:ListItem Value="False">Active</asp:ListItem>
            <asp:ListItem Value="True">Discontinued</asp:ListItem>
        </asp:RadioButtonList>
    </EditItemTemplate>
</asp:TemplateField>

이러한 변경 내용으로 인해 Discontinued 열이 확인란 목록에서 라디오 단추 쌍 목록으로 변환 되었습니다 (그림 14 참조).With these changes, the Discontinued column has been transformed from a list of checkboxes to a list of radio button pairs (see Figure 14). 제품을 편집 하는 경우 해당 라디오 단추가 선택 되 고, 다른 라디오 단추를 선택 하 고 업데이트를 클릭 하 여 제품의 단종 된 상태를 업데이트할 수 있습니다.When editing a product, the appropriate radio button is selected and the product's discontinued status can be updated by selecting the other radio button and clicking Update.

지원 되지 않는 확인란이 라디오 단추 쌍으로 대체 The Discontinued CheckBoxes Have Been Replaced by Radio Button Pairs

그림 14: 단종 된 확인란이 라디오 단추 쌍으로 대체 되었습니다 (전체 크기 이미지를 보려면 클릭).Figure 14: The Discontinued CheckBoxes Have Been Replaced by Radio Button Pairs (Click to view full-size image)

Note

Products 데이터베이스의 Discontinued 열에는 NULL 값이 포함 될 수 없으므로 인터페이스에서 NULL 정보를 캡처하는 데 걱정할 필요가 없습니다.Since the Discontinued column in the Products database cannot have NULL values, we do not need to worry about capturing NULL information in the interface. 그러나 Discontinued 열에 NULL 값이 포함 될 수 있는 경우 category 및 공급자 Dropdownlist 같이 Value 빈 문자열 (Value="")로 설정 된 세 번째 라디오 단추를 목록에 추가 하려고 합니다.If, however, Discontinued column could contain NULL values we'd want to add a third radio button to the list with its Value set to an empty string (Value=""), just like with the category and supplier DropDownLists.

요약Summary

BoundField 및 CheckBoxField는 읽기 전용, 편집 및 삽입 인터페이스를 자동으로 렌더링 하지만 사용자 지정 기능을 제공 하지는 않습니다.While the BoundField and CheckBoxField automatically render read-only, editing, and inserting interfaces, they lack the ability for customization. 그러나 종종 이전 자습서에서 살펴본 것 처럼 유효성 검사 컨트롤을 추가 하거나이 자습서에서 살펴본 것 처럼 데이터 컬렉션 사용자 인터페이스를 사용자 지정 하 여 편집 또는 삽입 인터페이스를 사용자 지정 해야 합니다.Often, though, we'll need to customize the editing or inserting interface, perhaps adding validation controls (as we saw in the preceding tutorial) or by customizing the data collection user interface (as we saw in this tutorial). Templatefield로 변환를 사용 하 여 인터페이스를 사용자 지정 하는 작업은 다음 단계에서 합계를 계산할 수 있습니다.Customizing the interface with a TemplateField can be summed up in the following steps:

  1. Templatefield로 변환를 추가 하거나 기존 BoundField 또는 CheckBoxField를 Templatefield로 변환로 변환 합니다.Add a TemplateField or convert an existing BoundField or CheckBoxField into a TemplateField
  2. 필요에 따라 인터페이스 보강Augment the interface as needed
  3. 양방향 데이터 바인딩을 사용 하 여 새로 추가 된 웹 컨트롤에 적절 한 데이터 필드 바인딩Bind the appropriate data fields to the newly added Web controls using two-way databinding

기본 제공 ASP.NET 웹 컨트롤 외에도 사용자 지정, 컴파일된 서버 컨트롤 및 사용자 정의 컨트롤을 사용 하 여 Templatefield로 변환의 템플릿을 사용자 지정할 수 있습니다.In addition to using the built-in ASP.NET Web controls, you can also customize the templates of a TemplateField with custom, compiled server controls and User Controls.

행복 한 프로그래밍Happy Programming!

저자 정보About the Author

Scott Mitchell(7 개의 ASP/ASP. NET books 및 4GuysFromRolla.com창립자)은 1998부터 Microsoft 웹 기술을 사용 하 여 작업 했습니다.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott은 독립 컨설턴트, 강사 및 기록기로 작동 합니다.Scott works as an independent consultant, trainer, and writer. 최신 책은 24 시간 이내에 ASP.NET 2.0을 sams teach yourself것입니다.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. mitchell@4GuysFromRolla.com에 도달할 수 있습니다 .He can be reached at mitchell@4GuysFromRolla.com. 또는 블로그를 통해 http://ScottOnWriting.NET에서 찾을 수 있습니다.or via his blog, which can be found at http://ScottOnWriting.NET.