로 스콧 미첼
페이지에서 "모두 업데이트" 단추를 클릭하여 모든 항목이 편집 모드이고 값을 저장할 수 있는 완전히 편집 가능한 DataList를 만드는 방법을 알아봅니다.
소개
이전 자습서에서는 항목 수준 DataList를 만드는 방법을 검토했습니다. 표준 편집 가능한 GridView와 마찬가지로 DataList의 각 항목에는 항목을 편집할 수 있도록 하는 편집 단추가 포함되어 있습니다. 이 항목 수준 편집은 가끔만 업데이트되는 데이터에 적합하지만 특정 사용 사례 시나리오에서는 사용자가 많은 레코드를 편집해야 합니다. 사용자가 수십 개의 레코드를 편집해야 하고 편집을 클릭하고 변경한 다음 각 레코드에 대한 업데이트를 클릭해야 하는 경우 클릭 양이 생산성을 저해할 수 있습니다. 이러한 경우 모든 항목이 편집 모드에 있고 페이지에서 모두 업데이트 단추를 클릭하여 값을 편집할 수 있는 완전히 편집 가능한 DataList를 제공하는 것이 더 좋습니다(그림 1 참조).
그림 1: 완전히 편집 가능한 DataList의 각 항목을 수정할 수 있습니다(전체 크기 이미지를 보려면 클릭).
이 자습서에서는 사용자가 완전히 편집 가능한 DataList를 사용하여 공급업체 주소 정보를 업데이트할 수 있도록 하는 방법을 살펴봅니다.
1단계: DataList의 ItemTemplate에서 편집 가능한 사용자 인터페이스 만들기
항목 수준 편집 가능한 표준 DataList를 만드는 이전 자습서에서는 다음 두 가지 템플릿을 사용했습니다.
-
ItemTemplate에는 읽기 전용 사용자 인터페이스(각 제품의 이름과 가격을 표시하기 위한 레이블 웹 컨트롤)가 포함되어 있습니다. -
EditItemTemplate에는 편집 모드 사용자 인터페이스(두 개의 TextBox 웹 컨트롤)가 포함되어 있습니다.
DataList의 EditItemIndex 속성은 .를 사용하여 렌더링되는 항목 DataListItem (있는 경우)을 EditItemTemplate지정합니다. 특히 해당 값이 DataListItemItemIndex DataList의 EditItemIndex 속성과 일치하는 값은 .를 EditItemTemplate사용하여 렌더링됩니다. 이 모델은 한 번에 하나의 항목만 편집할 수 있지만 완전히 편집 가능한 DataList를 만들 때는 무너질 때 잘 작동합니다.
완전히 편집 가능한 DataList의 경우 편집 가능한 인터페이스를 사용하여 모든DataListItem합니다. 이 작업을 수행하는 가장 간단한 방법은 .에서 편집 가능한 인터페이스를 정의하는 것입니다 ItemTemplate. 공급자 주소 정보를 수정하기 위해 편집 가능한 인터페이스는 공급자 이름을 텍스트로 포함하고 주소, 도시 및 국가/지역 값에 대한 TextBoxes를 포함합니다.
먼저 페이지를 열고 BatchUpdate.aspx DataList 컨트롤을 추가하고 해당 ID 속성을 Suppliers.로 설정합니다. DataList의 스마트 태그에서 명명 SuppliersDataSource된 새 ObjectDataSource 컨트롤을 추가하도록 선택합니다.
그림 2: 명명된 SuppliersDataSource 새 ObjectDataSource 만들기(전체 크기 이미지를 보려면 클릭)
클래스 메서드 SuppliersBLL 를 사용하여 데이터를 검색하도록 ObjectDataSource를 GetSuppliers() 구성합니다(그림 3 참조). 이전 자습서와 마찬가지로 ObjectDataSource를 통해 공급자 정보를 업데이트하는 대신 비즈니스 논리 계층으로 직접 작업합니다. 따라서 업데이트 탭에서 드롭다운 목록을 (없음)으로 설정합니다(그림 4 참조).
그림 3: 메서드를 GetSuppliers() 사용하여 공급업체 정보 검색(전체 크기 이미지를 보려면 클릭)
그림 4: 업데이트 탭에서 드롭다운 목록을 (없음)으로 설정합니다(전체 크기 이미지를 보려면 클릭).
마법사를 완료한 후 Visual Studio는 DataList를 ItemTemplate 자동으로 생성하여 레이블 웹 컨트롤의 데이터 원본에서 반환된 각 데이터 필드를 표시합니다. 대신 편집 인터페이스를 제공하려면 이 템플릿을 수정해야 합니다.
ItemTemplate DataList의 스마트 태그에서 템플릿 편집 옵션을 사용하거나 선언적 구문을 통해 직접 디자이너를 통해 사용자 지정할 수 있습니다.
잠시 시간을 내어 공급자의 이름을 텍스트로 표시하지만 공급자 주소, 도시 및 국가/지역 값에 대한 TextBoxes를 포함하는 편집 인터페이스를 만듭니다. 이러한 변경을 수행한 후 페이지의 선언적 구문은 다음과 유사하게 표시됩니다.
<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
DataSourceID="SuppliersDataSource">
<ItemTemplate>
<h4><asp:Label ID="CompanyNameLabel" runat="server"
Text='<%# Eval("CompanyName") %>' /></h4>
<table border="0">
<tr>
<td class="SupplierPropertyLabel">Address:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Address" runat="server"
Text='<%# Eval("Address") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">City:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="City" runat="server"
Text='<%# Eval("City") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">Country:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Country" runat="server"
Text='<%# Eval("Country") %>' />
</td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>
참고 항목
이전 자습서와 마찬가지로 이 자습서의 DataList는 뷰 상태를 사용하도록 설정해야 합니다.
I에서는 ItemTemplate 두 개의 새 CSS 클래스를 사용하고 있으며SupplierPropertyLabel, SupplierPropertyValue 클래스에 Styles.css 추가되고 CSS 클래스와 ProductPropertyLabel 동일한 스타일 설정을 ProductPropertyValue 사용하도록 구성되었습니다.
.ProductPropertyLabel, .SupplierPropertyLabel
{
font-weight: bold;
text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
padding-right: 35px;
}
변경한 후 브라우저를 통해 이 페이지를 방문합니다. 그림 5와 같이 각 DataList 항목은 공급자 이름을 텍스트로 표시하고 TextBoxes를 사용하여 주소, 도시 및 국가/지역을 표시합니다.
그림 5: DataList의 각 공급업체가 편집 가능(전체 크기 이미지를 보려면 클릭)
2단계: 모두 업데이트 단추 추가
그림 5의 각 공급업체에는 TextBox에 주소, 도시 및 국가/지역 필드가 표시되지만 현재는 업데이트 단추를 사용할 수 없습니다. 항목당 업데이트 단추를 사용하는 대신, 완전히 편집 가능한 DataList를 사용하는 경우 일반적으로 페이지에는 DataList의 모든 레코드를 업데이트하는 단일 업데이트 모두 단추가 있습니다. 이 자습서에서는 페이지 맨 위에 하나씩, 아래쪽에 하나씩 두 개의 [모두 업데이트] 단추를 추가해 보겠습니다(두 단추를 클릭하면 동일한 효과가 있음).
먼저 DataList 위에 단추 웹 컨트롤을 추가하고 해당 ID 속성을 .로 UpdateAll1설정합니다. 다음으로 DataList 아래에 두 번째 단추 웹 컨트롤을 추가하고 해당 ID 컨트롤을 UpdateAll2.로 설정합니다. 두 단추의 Text 속성을 모두 업데이트하도록 설정합니다. 마지막으로 두 단추 이벤트에 대한 이벤트 처리기를 만듭니다 Click . 각 이벤트 처리기에서 업데이트 논리를 복제하는 대신 이벤트 처리기가 이 세 번째 메서드를 호출하도록 하여 해당 논리를 세 번째 메서드 UpdateAllSupplierAddresses로 리팩터링해 보겠습니다.
Protected Sub UpdateAll1_Click(sender As Object, e As EventArgs) _
Handles UpdateAll1.Click
UpdateAllSupplierAddresses()
End Sub
Protected Sub UpdateAll2_Click(sender As Object, e As EventArgs) _
Handles UpdateAll2.Click
UpdateAllSupplierAddresses()
End Sub
Private Sub UpdateAllSupplierAddresses()
' TODO: Write code to update _all_ of the supplier addresses in the DataList
End Sub
그림 6은 모두 업데이트 단추가 추가된 후의 페이지를 보여 줍니다.
그림 6: 페이지에 두 개의 업데이트 모든 단추가 추가되었습니다(전체 크기 이미지를 보려면 클릭).
3단계: 모든 공급업체 주소 정보 업데이트
모든 DataList 항목이 편집 인터페이스를 표시하고 모두 업데이트 단추가 추가되면 나머지 모든 항목은 일괄 업데이트를 수행하기 위해 코드를 작성하는 것입니다. 특히 DataList의 항목을 반복하고 각 항목에 대한 클래스 메서드 SuppliersBLL 를 UpdateSupplierAddress 호출해야 합니다.
DataList를 구성하는 인스턴스의 DataListItem 컬렉션은 DataList의 Items 속성을 통해 액세스할 수 있습니다. 참조를 DataListItem사용하여 컬렉션에서 해당 SupplierID 컨트롤을 잡고 다음 코드와 DataKeys 같이 프로그래밍 방식으로 TextBox 웹 컨트롤을 ItemTemplate 참조할 수 있습니다.
Private Sub UpdateAllSupplierAddresses()
' Create an instance of the SuppliersBLL class
Dim suppliersAPI As New SuppliersBLL()
' Iterate through the DataList's items
For Each item As DataListItem In Suppliers.Items
' Get the supplierID from the DataKeys collection
Dim supplierID As Integer = Convert.ToInt32(Suppliers.DataKeys(item.ItemIndex))
' Read in the user-entered values
Dim address As TextBox = CType(item.FindControl("Address"), TextBox)
Dim city As TextBox = CType(item.FindControl("City"), TextBox)
Dim country As TextBox = CType(item.FindControl("Country"), TextBox)
Dim addressValue As String = Nothing, _
cityValue As String = Nothing, _
countryValue As String = Nothing
If address.Text.Trim().Length > 0 Then
addressValue = address.Text.Trim()
End If
If city.Text.Trim().Length > 0 Then
cityValue = city.Text.Trim()
End If
If country.Text.Trim().Length > 0 Then
countryValue = country.Text.Trim()
End If
' Call the SuppliersBLL class's UpdateSupplierAddress method
suppliersAPI.UpdateSupplierAddress _
(supplierID, addressValue, cityValue, countryValue)
Next
End Sub
사용자가 모두 업데이트 단추 중 하나를 클릭하면 메서드가 DataList의 각 UpdateAllSupplierAddressesDataListItem 단추를 Suppliers 반복하고 클래스의 SuppliersBLL 메서드를 UpdateSupplierAddress 호출하여 해당 값을 전달합니다. 주소, 도시 또는 국가/지역 패스에 대해 입력하지 않은 값은 빈 문자열이 아닌 값으로 NothingUpdateSupplierAddress , 기본 레코드 필드에 대한 데이터베이스 NULL 가 생성됩니다.
참고 항목
향상된 기능으로 일괄 업데이트가 수행된 후 일부 확인 메시지를 제공하는 상태 레이블 웹 컨트롤을 페이지에 추가할 수 있습니다.
수정된 주소만 업데이트
이 자습서에 사용되는 일괄 업데이트 알고리즘은 주소 정보가 변경되었는지 여부에 관계없이 DataList의 모든UpdateSupplierAddress메서드를 호출 합니다. 이러한 블라인드 업데이트는 일반적으로 성능 문제가 아니지만 데이터베이스 테이블의 변경 내용을 감사하는 경우 불필요한 레코드로 이어질 수 있습니다. 예를 들어 트리거를 사용하여 테이블에 대한 모든 UPDATESuppliers 정보를 감사 테이블에 기록하는 경우 사용자가 [모두 업데이트] 단추를 클릭할 때마다 사용자가 변경했는지 여부에 관계없이 시스템의 각 공급업체에 대해 새 감사 레코드가 만들어집니다.
ADO.NET DataTable 및 DataAdapter 클래스는 수정, 삭제 및 새 레코드로 인해 데이터베이스 통신이 발생하는 일괄 업데이트를 지원하도록 설계되었습니다. DataTable의 각 행에는 RowState 행이 DataTable에 추가되었는지, 해당 행에서 삭제되었는지, 수정되었는지 또는 변경되지 않은 상태로 유지되는지를 나타내는 속성 이 있습니다. DataTable이 처음에 채워지면 모든 행이 변경되지 않은 것으로 표시됩니다. 행 열의 값을 변경하면 행이 수정된 것으로 표시됩니다.
SuppliersBLL 클래스에서 먼저 단일 공급자 레코드를 읽어 지정된 공급자의 주소 정보를 a SuppliersDataTable 로 업데이트한 다음, 다음 코드를 사용하여 , Address및 City 열 값을 설정합니다Country.
Public Function UpdateSupplierAddress _
(supplierID As Integer, address As String, city As String, country As String) _
As Boolean
Dim suppliers As Northwind.SuppliersDataTable = _
Adapter.GetSupplierBySupplierID(supplierID)
If suppliers.Count = 0 Then
' no matching record found, return false
Return False
Else
Dim supplier As Northwind.SuppliersRow = suppliers(0)
If address Is Nothing Then
supplier.SetAddressNull()
Else
supplier.Address = address
End If
If city Is Nothing Then
supplier.SetCityNull()
Else
supplier.City = city
End If
If country Is Nothing Then
supplier.SetCountryNull()
Else
supplier.Country = country
End If
' Update the supplier Address-related information
Dim rowsAffected As Integer = Adapter.Update(supplier)
' Return true if precisely one row was updated, otherwise false
Return rowsAffected = 1
End If
End Function
이 코드는 값이 변경되었는지 여부에 관계없이 전달된 주소, 도시 및 국가/지역 값을 SuppliersRow in에 SuppliersDataTable 순진하게 할당합니다. 이러한 수정으로 인해 s SuppliersRow 속성이 RowState 수정된 것으로 표시됩니다. 데이터 액세스 계층 메서드 Update 가 호출되면 수정된 것으로 SupplierRow 확인되므로 데이터베이스에 UPDATE 명령을 보냅니다.
그러나 전달된 주소, 도시 및 국가/지역 값이 기존 값과 다른 SuppliersRow 경우에만 할당하도록 이 메서드에 코드를 추가했다고 가정해 보겠습니다. 주소, 도시 및 국가/지역이 기존 데이터와 동일한 경우 변경되지 SupplierRowRowState 않으며 s는 변경되지 않은 것으로 표시됩니다. 결과적으로 DAL 메서드 Update 가 호출되면 수정되지 않았기 때문에 데이터베이스 호출이 SuppliersRow 이루어지지 않습니다.
이 변경을 적용하려면 전달된 주소, 도시 및 국가/지역 값을 다음 코드로 맹목적으로 할당하는 문을 바꿉니다.
' Only assign the values to the SupplierRow's column values if they differ
If address Is Nothing AndAlso Not supplier.IsAddressNull() Then
supplier.SetAddressNull()
ElseIf (address IsNot Nothing AndAlso supplier.IsAddressNull) _
OrElse (Not supplier.IsAddressNull() AndAlso _
String.Compare(supplier.Address, address) <> 0) Then
supplier.Address = address
End If
If city Is Nothing AndAlso Not supplier.IsCityNull() Then
supplier.SetCityNull()
ElseIf (city IsNot Nothing AndAlso supplier.IsCityNull) _
OrElse (Not supplier.IsCityNull() AndAlso _
String.Compare(supplier.City, city) <> 0) Then
supplier.City = city
End If
If country Is Nothing AndAlso Not supplier.IsCountryNull() Then
supplier.SetCountryNull()
ElseIf (country IsNot Nothing AndAlso supplier.IsCountryNull) _
OrElse (Not supplier.IsCountryNull() AndAlso _
String.Compare(supplier.Country, country) <> 0) Then
supplier.Country = country
End If
이 추가된 코드를 사용하여 DAL 메서드 Update 는 주소 관련 값이 변경된 레코드에 대해서만 문을 데이터베이스에 보냅니 UPDATE 다.
또는 전달된 주소 필드와 데이터베이스 데이터 간에 차이가 있는지 여부를 추적할 수 있으며, 없는 경우 DAL Update 메서드에 대한 호출을 무시하기만 하면 됩니다. 이 방법은 DB 직접 메서드를 사용하는 경우 DB 직접 메서드가 데이터베이스 호출이 실제로 필요한지 여부를 확인하기 위해 확인할 수 있는 SuppliersRow 인스턴스를 전달 RowState 하지 않으므로 잘 작동합니다.
참고 항목
메서드가 UpdateSupplierAddress 호출될 때마다 데이터베이스를 호출하여 업데이트된 레코드에 대한 정보를 검색합니다. 그런 다음 데이터가 변경되면 테이블 행을 업데이트하기 위해 데이터베이스에 대한 또 다른 호출이 이루어집니다. 이 워크플로는 페이지의 모든UpdateSupplierAddress를 EmployeesDataTable 허용하는 메서드 오버로드를 만들어 최적화할 수 있습니다. 그런 다음 데이터베이스를 한 번 호출하여 테이블에서 모든 레코드 Suppliers 를 가져올 수 있습니다. 그런 다음 두 결과 집합을 열거할 수 있으며 변경이 발생한 레코드만 업데이트할 수 있습니다.
요약
이 자습서에서는 사용자가 여러 공급업체의 주소 정보를 신속하게 수정할 수 있도록 완전히 편집 가능한 DataList를 만드는 방법을 알아보았습니다. 먼저 DataList ItemTemplate의 공급자 주소, 도시 및 국가/지역 값에 대한 TextBox 웹 컨트롤 편집 인터페이스를 정의했습니다. 다음으로 DataList 위와 아래에 모든 업데이트 단추를 추가했습니다. 사용자가 변경한 후 모두 업데이트 단추 DataListItem 중 하나를 클릭하면 s가 열거되고 클래스 메서드 SuppliersBLL 를 호출합니다UpdateSupplierAddress.
행복한 프로그래밍!
작성자 정보
7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 샘스 티치 자신 ASP.NET 24 시간에 2.0입니다. 그에게 mitchell@4GuysFromRolla.com으로 연락할 수 있습니다.
특별 감사
이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 잭 존스와 켄 페스피사였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 mitchell@4GuysFromRolla.com으로 메시지를 보내 주세요.