작성자: 스콧 미첼
이 자습서에서는 GridView 컨트롤에 라디오 단추 열을 추가하여 사용자에게 GridView의 단일 행을 선택하는 보다 직관적인 방법을 제공하는 방법을 살펴봅니다.
소개
GridView 컨트롤은 다양한 기본 제공 기능을 제공합니다. 여기에는 텍스트, 이미지, 하이퍼링크 및 단추를 표시하기 위한 다양한 필드가 포함됩니다. 추가 사용자 지정을 위한 템플릿을 지원합니다. 마우스를 몇 번 클릭하면 단추를 통해 각 행을 선택할 수 있는 GridView를 만들거나 기능을 편집하거나 삭제할 수 있습니다. 제공된 기능의 과다에도 불구하고 지원되지 않는 추가 기능을 추가해야 하는 경우가 종종 있습니다. 이 자습서와 다음 두 자습서에서는 추가 기능을 포함하도록 GridView의 기능을 향상시키는 방법을 살펴봅니다.
이 자습서와 다음 자습서에서는 행 선택 프로세스를 향상시키는 데 중점을 두고 있습니다.
선택 가능한 마스터 GridView 및 세부 정보 DetailView를 사용하는 마스터/세부 정보에서 분석했듯이, Select 단추가 포함된 CommandField를 GridView에 추가할 수 있습니다. 클릭하면 포스트백이 계속되고 GridView의 SelectedIndex
속성이 선택 단추를 클릭한 행의 인덱스로 업데이트됩니다.
Master/Detail에서 선택 가능한 Master GridView를 사용한 DetailView 자습서에서 이 기능을 사용하여 선택한 GridView 행의 세부 정보를 표시하는 방법을 살펴보았습니다.
선택 단추는 많은 상황에서 작동하지만 다른 사용자도 작동하지 않을 수 있습니다. 단추를 사용하는 대신 라디오 단추와 확인란이라는 두 가지 다른 사용자 인터페이스 요소가 일반적으로 선택 영역에 사용됩니다. 선택 단추 대신 각 행에 라디오 단추 또는 확인란이 포함되도록 GridView를 보강할 수 있습니다. 사용자가 GridView 레코드 중 하나만 선택할 수 있는 시나리오에서는 선택 단추보다 라디오 단추를 선호할 수 있습니다. 사용자가 웹 기반 전자 메일 애플리케이션과 같은 여러 레코드를 선택할 수 있는 경우 사용자가 여러 메시지를 선택하여 확인란을 삭제하려는 경우 선택 단추 또는 라디오 단추 사용자 인터페이스에서 사용할 수 없는 기능을 제공합니다.
이 자습서에서는 GridView에 라디오 단추 열을 추가하는 방법을 살펴봅니다. 진행 자습서에서는 확인란을 사용하여 탐색합니다.
1단계: GridView 웹 페이지 향상 만들기
라디오 단추 열을 포함하도록 GridView를 향상시키기 전에 먼저 이 자습서와 다음 두 가지에 필요한 웹 사이트 프로젝트에서 ASP.NET 페이지를 만들어 보겠습니다. 먼저 .라는 EnhancedGridView
새 폴더를 추가합니다. 다음으로, 다음 ASP.NET 페이지를 해당 폴더에 추가하여 각 페이지를 마스터 페이지와 Site.master
연결해야 합니다.
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
그림 1: SqlDataSource-Related 자습서의 ASP.NET 페이지 추가
다른 폴더처럼 Default.aspx
폴더에 있는 EnhancedGridView
는 해당 섹션의 자습서를 나열할 것입니다. 사용자 컨트롤이 SectionLevelTutorialListing.ascx
이 기능을 제공한다는 점을 기억하세요. 따라서 솔루션 탐색기에서 이 사용자 컨트롤 Default.aspx
을 페이지의 디자인 보기로 끌어 추가하십시오.
그림 2: 사용자 정의 컨트롤 추가 SectionLevelTutorialListing.ascx
Default.aspx
(전체 크기 이미지를 보려면 클릭)
마지막으로 이 네 페이지를 파일에 항목으로 추가합니다 Web.sitemap
. 특히 SqlDataSource 컨트롤 <siteMapNode>
사용 후 다음 태그를 추가합니다.
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
업데이트 Web.sitemap
한 후 잠시 브라우저를 통해 자습서 웹 사이트를 봅니다. 이제 왼쪽 메뉴에는 자습서 편집, 삽입 및 삭제를 위한 항목이 포함되어 있습니다.
그림 3: 이제 사이트 맵에 GridView 자습서 향상을 위한 항목이 포함됩니다.
2단계: GridView에 공급업체 표시
이 자습서에서는 각 GridView 행에 라디오 단추를 제공하는 미국의 공급업체를 나열하는 GridView를 빌드해 보겠습니다. 라디오 단추를 통해 공급업체를 선택한 후 사용자는 단추를 클릭하여 공급업체 제품을 볼 수 있습니다. 이 작업은 사소한 것처럼 들릴 수 있지만, 특히 까다로울 수 있는 미묘한 차이가 많이 있습니다. 이러한 미묘한 차이를 살펴보기 전에 먼저 공급업체를 나열하는 GridView를 살펴보겠습니다.
먼저 폴더에서 RadioButtonField.aspx
페이지를 열고, 도구 상자에서 GridView를 디자이너로 끌어다 놓습니다EnhancedGridView
. GridView의 ID
를 Suppliers
로 설정하고 스마트 태그에서 새 데이터 원본을 만들도록 선택합니다. 특히 SuppliersDataSource
객체에서 데이터를 가져오는 SuppliersBLL
라는 이름의 ObjectDataSource를 생성합니다.
그림 4: 새 ObjectDataSource 이름 SuppliersDataSource
만들기(전체 크기 이미지를 보려면 클릭)
그림 5: 클래스를 사용하도록 SuppliersBLL
ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
미국에서 해당 공급업체만 나열하려고 하므로 SELECT 탭의 GetSuppliersByCountry(country)
드롭다운 목록에서 메서드를 선택합니다.
그림 6: 클래스를 사용하도록 SuppliersBLL
ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
업데이트 탭에서 (없음) 옵션을 선택하고 다음을 클릭합니다.
그림 7: 클래스를 사용하도록 SuppliersBLL
ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
메서드는 GetSuppliersByCountry(country)
매개 변수를 허용하므로 데이터 원본 구성 마법사에서 해당 매개 변수의 원본을 묻는 메시지를 표시합니다. 하드 코딩된 값(미국, 이 예제에서는)을 지정하려면 매개 변수 원본 드롭다운 목록을 None으로 설정하고 텍스트 상자에 기본값을 입력합니다. 마침을 클릭하여 마법사를 완료합니다.
그림 8: 매개 변수의 기본값 country
으로 USA 사용(전체 크기 이미지를 보려면 클릭)
마법사를 완료한 후 GridView에는 각 공급업체 데이터 필드에 대한 BoundField가 포함됩니다.
CompanyName
, City
, 그리고 Country
BoundFields를 제외한 모든 것을 제거하고 CompanyName
BoundFields의 HeaderText
속성을 Supplier로 바꿉니다. 이렇게 하면 GridView 및 ObjectDataSource 선언적 구문이 다음과 유사하게 표시됩니다.
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
이 자습서에서는 사용자가 공급자 목록과 동일한 페이지 또는 다른 페이지에서 선택한 공급업체 제품을 볼 수 있도록 허용해 보겠습니다. 이를 수용하려면 페이지에 두 개의 단추 웹 컨트롤을 추가합니다. 이 두 버튼의 ID
을 설정했습니다. ListProducts
을 클릭하면 포스트백이 발생하고 선택한 공급업체의 제품이 같은 페이지에 나열됩니다. 그러나 SendToProducts
을 클릭하면 사용자는 제품을 나열하는 다른 페이지로 이동하게 됩니다.
그림 9는 브라우저를 Suppliers
통해 볼 때 GridView와 두 개의 단추 웹 컨트롤을 보여 줍니다.
그림 9: 미국의 공급업체의 이름, 도시 및 국가 정보가 나열되어 있습니다(전체 크기 이미지를 보려면 클릭).
3단계: 라디오 버튼 열 추가
이 시점에서 Suppliers
GridView에는 미국에 있는 각 공급업체의 회사 이름, 도시 및 국가를 표시하는 세 개의 BoundFields가 있습니다. 그러나 여전히 라디오 단추 열이 부족합니다. 아쉽게도 GridView에는 기본 제공 RadioButtonField가 포함되지 않습니다. 그렇지 않다면 그리드에 추가하여 바로 완료할 수 있을 텐데요. 대신 TemplateField를 추가하고 라디오 단추를 렌더링하도록 구성 ItemTemplate
하여 각 GridView 행에 라디오 단추를 만들 수 있습니다.
처음에는 TemplateField에 RadioButton 웹 컨트롤을 추가하여 원하는 사용자 인터페이스를 구현할 수 있다고 가정할 ItemTemplate
수 있습니다. 실제로 GridView의 각 행에 단일 라디오 단추를 추가하지만 라디오 단추를 그룹화할 수 없으므로 상호 배타적이지 않습니다. 즉, 최종 사용자는 GridView에서 동시에 여러 라디오 단추를 선택할 수 있습니다.
RadioButton 웹 컨트롤의 TemplateField는 우리가 필요한 기능을 제공하지 않지만, 결과적으로 라디오 버튼이 그룹화되지 않는 이유를 알아보는 것이 중요합니다. 먼저 Suppliers GridView에 TemplateField를 추가하여 맨 왼쪽 필드로 만듭니다. 그런 다음 GridView의 스마트 태그에서 템플릿 편집 링크를 클릭하고 도구 상자에서 TemplateField ItemTemplate
로 RadioButton 웹 컨트롤을 끕니다(그림 10 참조). RadioButton의 ID
속성을 RowSelector
로 설정하고 GroupName
속성을 SuppliersGroup
로 설정합니다.
그림 10: RadioButton 웹 컨트롤을 ItemTemplate
추가합니다(전체 크기 이미지를 보려면 클릭).
디자이너를 통해 이러한 추가 작업을 수행한 후 GridView의 태그는 다음과 유사하게 표시됩니다.
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
RadioButton의 GroupName
속성 은 일련의 라디오 단추를 그룹화하는 데 사용됩니다. 동일한 GroupName
값을 가진 모든 RadioButton 컨트롤은 그룹화된 것으로 간주되며 한 번에 하나의 라디오 단추만 그룹에서 선택할 수 있습니다. 이 속성은 GroupName
렌더링된 라디오 버튼의 name
속성에 대한 값을 지정합니다. 브라우저는 라디오 단추 name
특성을 검사하여 라디오 단추 그룹화가 결정됩니다.
RadioButton 웹 컨트롤을 ItemTemplate
에 추가한 후, 브라우저를 통해 이 페이지를 방문하여 격자 행의 라디오 버튼을 클릭합니다. 그림 11과 같이 라디오 단추가 그룹화되지 않아 모든 행을 선택할 수 있습니다.
그림 11: GridView의 라디오 단추가 그룹화되지 않음(전체 크기 이미지를 보려면 클릭)
라디오 단추가 그룹화되지 않는 이유는 동일한 name
속성 설정에도 불구하고 렌더링된 GroupName
특성이 다르기 때문입니다. 이러한 차이점을 확인하려면 브라우저에서 보기/원본을 수행하고 라디오 단추 태그를 검사합니다.
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
속성 창에 지정된 값과 정확히 일치하지 않고 여러 다른 name
값들 앞에 추가된 id
및 ID
특성을 확인하세요. 렌더링된 ID
및 id
속성 앞에 추가된 name
값은 라디오 버튼의 부모 컨트롤인 ID
s, GridView의 GridViewRow
, 컨텐츠 컨트롤의 ID
, 웹 폼의 ID
s 입니다. GridView에서 렌더링된 각 웹 컨트롤에 고유 ID
하고 id
값이 있도록 이러한 name
항목이 추가됩니다.
렌더링된 각 컨트롤은 서로 다른 name
id
것이 필요하며, 이는 브라우저가 클라이언트 쪽의 각 컨트롤을 고유하게 식별하는 방식과 포스트백 시 발생한 작업 또는 변경 내용을 웹 서버에 식별하는 방식이기 때문입니다. 예를 들어 RadioButton의 확인 상태가 변경될 때마다 일부 서버 쪽 코드를 실행하려고 하는 경우를 생각해 보겠습니다. RadioButton의 AutoPostBack
속성을 True
로 설정하고 CheckChanged
이벤트에 대한 이벤트 처리기를 만들어서 이 작업을 수행할 수 있습니다. 그러나 모든 라디오 버튼에 대해 렌더링된 name
및 id
값이 동일한 경우, 포스트백에서 어떤 특정한 라디오 버튼이 클릭되었는지 확인할 수 없습니다.
간단히 말해서 RadioButton 웹 컨트롤을 사용하여 GridView에서 라디오 단추 열을 만들 수 없다는 것입니다. 대신, 적절한 태그가 각 GridView 행에 삽입되도록 하기 위해 다소 오래된 기술을 사용해야 합니다.
비고
RadioButton 웹 컨트롤과 마찬가지로 템플릿에 추가할 때 라디오 단추 HTML 컨트롤에는 고유 name
특성이 포함되므로 그리드의 라디오 단추가 그룹화되지 않습니다. HTML 컨트롤에 익숙하지 않은 경우 특히 ASP.NET 2.0에서 HTML 컨트롤이 거의 사용되지 않으므로 이 메모를 무시해도 됩니다. 그러나 자세히 알아보려면 K. Scott Allen 의 블로그 항목 웹 컨트롤 및 HTML 컨트롤을 참조하세요.
리터럴 컨트롤을 이용해 라디오 버튼 마크업을 삽입하기
GridView 내의 모든 라디오 단추를 올바르게 그룹화하려면 라디오 단추 태그 ItemTemplate
를 수동으로 삽입해야 합니다. 각 라디오 단추에는 동일한 name
특성이 필요하지만 고유한 id
특성이 있어야 합니다(클라이언트 쪽 스크립트를 통해 라디오 단추에 액세스하려는 경우). 사용자가 라디오 단추를 선택하고 페이지를 다시 게시하면 브라우저에서 선택한 라디오 단추 특성의 value
값을 다시 보냅니다. 따라서 각 라디오 단추에는 고유한 value
특성이 필요합니다. 마지막으로, 포스트백 시 선택한 하나의 라디오 단추에 특성을 추가 checked
해야 합니다. 그렇지 않으면 사용자가 선택하고 다시 게시한 후에는 라디오 단추가 기본 상태로 돌아갑니다(모두 선택되지 않음).
템플릿에 하위 수준 태그를 삽입하기 위해 수행할 수 있는 두 가지 방법이 있습니다. 하나는 코드 숨김 클래스에 정의된 형식 지정 메서드에 대한 태그와 호출을 혼합하여 수행하는 것입니다. 이 기술은 GridView 컨트롤 자습서의 TemplateFields 사용 자습서에서 처음 설명했습니다. 이 경우 다음과 같이 표시될 수 있습니다.
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
여기서는 GetUniqueRadioButton
GetRadioButtonValue
각 라디오 단추에 대한 적절한 id
value
특성 값을 반환하는 코드 숨김 클래스에 정의된 메서드입니다. 이 방법은 id
및 value
특성을 할당하는 데 잘 작동하지만, 데이터 바인딩 구문은 데이터가 처음으로 GridView에 바인딩될 때만 실행되기 때문에 checked
특성 값을 지정할 때 문제를 초래합니다. 따라서 GridView에서 뷰 상태를 사용하도록 설정한 경우 페이지가 처음 로드되거나 GridView가 데이터 원본에 명시적으로 반등할 때만 서식 지정 메서드가 실행되므로 특성을 설정하는 checked
함수는 포스트백 시 호출되지 않습니다. 그것은 다소 미묘한 문제이고 이 기사에서는 깊게 다루지 않으므로 여기서 마무리하도록 하겠습니다. 그러나 저는 위의 접근 방식을 시도하여 막힐 때까지 작업해보시길 권장합니다. 이러한 연습은 작업 버전에 더 가까워지지는 않지만 GridView 및 데이터 바인딩 수명 주기에 대한 심층적인 이해를 촉진하는 데 도움이 됩니다.
템플릿에 사용자 지정 하위 수준 태그를 삽입하는 다른 방법 및 이 자습서에 사용할 방법은 템플릿에 리터럴 컨트롤 을 추가하는 것입니다. 그런 다음 GridView RowCreated
또는 RowDataBound
이벤트 처리기에서 리터럴 컨트롤에 프로그래밍 방식으로 액세스하고 해당 Text
속성을 태그로 설정하여 내보낼 수 있습니다.
먼저 TemplateField ItemTemplate
에서 RadioButton을 제거하고 리터럴 컨트롤로 바꿔서 시작합니다. 리터럴 컨트롤 ID
을 RadioButtonMarkup
로 설정합니다.
그림 12: 리터럴 컨트롤을 ItemTemplate
추가합니다(전체 크기 이미지를 보려면 클릭).
다음으로 GridView RowCreated
이벤트에 대한 이벤트 처리기를 만듭니다. 데이터가 RowCreated
GridView에 반등하는지 여부에 관계없이 추가된 모든 행에 대해 이벤트가 한 번 발생합니다. 즉, 데이터가 뷰 상태에서 다시 로드될 때에도 포스트백 시에 RowCreated
이벤트가 계속 발생한다는 뜻이며, 이는 RowDataBound
이벤트가 데이터 웹 컨트롤에 명시적으로 바인딩될 때에만 발생하기 때문에 RowCreated
을 사용하는 이유입니다.
이 이벤트 처리기에서는 데이터 행을 처리하는 경우에만 진행하려고 합니다. 각 데이터 행에 대해 프로그램적으로 리터럴 컨트롤을 참조하고 해당 RadioButtonMarkup
속성을 내보낼 태그로 설정하려고 합니다. 다음 코드에 나타난 바와 같이, 내보낸 마크업은 name
속성이 SuppliersGroup
로 설정된 라디오 버튼을 생성합니다. 또한, id
속성이 RowSelectorX
로 설정되며, X는 GridView 행의 인덱스이고, value
속성 또한 GridView 행의 인덱스로 설정됩니다.
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex)
End If
End Sub
GridView 행이 선택되고 포스트백이 발생하면, 우리는 선택한 공급업체의 SupplierID
를 확인합니다. 따라서 각 라디오 단추의 값은 GridView 행의 인덱스가 아닌 실제 SupplierID
값이어야 한다고 생각할 수 있습니다. 이는 특정 상황에서 작동할 수 있지만 맹목적으로 받아들이고 처리하는 것은 보안 위험입니다 SupplierID
. 예를 들어 GridView는 미국의 공급업체만 나열합니다. 그러나 SupplierID
가 라디오 버튼에서 직접 전달되는 경우, 장난스러운 사용자가 SupplierID
값을 포스트백으로 보낼 때 조작하지 못하게 하려면 어떻게 해야 할까요? 행 인덱스를 value
로 사용하고, SupplierID
컬렉션에서 DataKeys
을 포스트백 시 가져오면 사용자가 GridView 행 중 하나와 연결된 SupplierID
값 중 하나만 사용하고 있는지 확인할 수 있습니다.
이 이벤트 처리기 코드를 추가한 후 브라우저에서 페이지를 테스트하는 데 1분이 소요됩니다. 먼저 그리드의 라디오 단추 하나만 한 번에 선택할 수 있습니다. 그러나 라디오 단추를 선택하고 단추 중 하나를 클릭하면 포스트백이 발생하고 라디오 단추가 모두 초기 상태로 되돌아갑니다(즉, 포스트백 시 선택한 라디오 단추가 더 이상 선택되지 않음). 이 문제를 해결하려면 RowCreated
이벤트 처리기를 포스트백으로 전송된 선택한 라디오 버튼 인덱스를 검사하여, 해당 행 인덱스가 일치하는 경우 내보내는 태그에 checked="checked"
특성을 추가하도록 해야 합니다.
포스트백이 발생하면 브라우저는 선택한 라디오 단추의 name
와 value
를 다시 보냅니다.
Request.Form("name")
을 사용하여 값을 프로그래밍 방식으로 검색할 수 있습니다.
이 속성은Request.Form
양식 변수를 나타내는 형식을 제공합니다NameValueCollection
. 양식 변수는 웹 페이지에 있는 양식 필드의 이름과 값이며, 포스트백이 계속될 때마다 웹 브라우저에서 다시 전송됩니다. GridView에서 라디오 단추의 렌더링된 name
특성이 있기 SuppliersGroup
때문에 웹 페이지가 다시 게시되면 브라우저가 웹 서버(다른 양식 필드와 함께)로 다시 전송 SuppliersGroup=valueOfSelectedRadioButton
됩니다. 이 정보는 Request.Form
속성에서 Request.Form("SuppliersGroup")
를 사용하여 액세스할 수 있습니다.
이벤트 처리기뿐만 아니라 버튼 웹 컨트롤의 RowCreated
이벤트 처리기에서도 선택한 라디오 버튼의 인덱스를 결정해야 하므로, 코드 숨김 클래스에 Click
속성을 추가하여 라디오 버튼이 선택되지 않은 경우에는 SuppliersSelectedIndex
를 반환하고, 하나의 라디오 버튼이 선택된 경우 그 선택된 인덱스를 반환하도록 해보겠습니다.
Private ReadOnly Property SuppliersSelectedIndex() As Integer
Get
If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
Return -1
Else
Return Convert.ToInt32(Request.Form("SuppliersGroup"))
End If
End Get
End Property
이 속성이 추가되면, checked="checked"
가 RowCreated
와 같을 때 SuppliersSelectedIndex
이벤트 처리기에서 e.Row.RowIndex
태그를 추가해야 한다는 것을 알게 됩니다. 다음 논리를 포함하도록 이벤트 처리기를 업데이트합니다.
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}"", e.Row.RowIndex)
' See if we need to add the "checked" attribute
If SuppliersSelectedIndex = e.Row.RowIndex Then
output.Text &= " checked="checked""
End If
' Add the closing tag
output.Text &= " />"
End If
End Sub
이 변경으로 선택한 라디오 단추는 포스트백 후에 선택된 상태로 유지됩니다. 이제 선택한 라디오 단추를 지정할 수 있으므로 페이지가 처음 방문되었을 때 첫 번째 GridView 행의 라디오 단추가 선택되도록 동작을 변경할 수 있습니다(기본적으로 현재 동작인 라디오 단추가 선택되지 않음). 기본적으로 첫 번째 라디오 단추를 선택하려면 문을 다음If SuppliersSelectedIndex = e.Row.RowIndex Then
으로 변경 If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then
하기만 하면됩니다.
이 시점에서 페이지 다시 로드 시 선택된 단일 GridView 행이 저장될 수 있도록 그룹화된 라디오 버튼 열을 GridView에 추가했습니다. 다음 단계는 선택한 공급업체에서 제공하는 제품을 표시하는 것입니다. 4단계에서는 사용자를 다른 페이지로 리디렉션하여 선택한 SupplierID
페이지를 따라 보내는 방법을 살펴보겠습니다. 5단계에서는 선택한 공급업체 제품을 동일한 페이지의 GridView에 표시하는 방법을 알아봅니다.
비고
TemplateField(이 긴 3단계의 초점)를 사용하는 대신 적절한 사용자 인터페이스 및 기능을 렌더링하는 사용자 지정 DataControlField
클래스를 만들 수 있습니다. 클래스는 DataControlField
BoundField, CheckBoxField, TemplateField 및 기타 기본 제공 GridView 및 DetailsView 필드가 파생되는 기본 클래스입니다. 사용자 지정 DataControlField
클래스를 만들면 선언적 구문을 사용하여 라디오 단추 열을 추가할 수 있으며 다른 웹 페이지 및 기타 웹 애플리케이션의 기능을 훨씬 쉽게 복제할 수 있습니다.
그러나 ASP.NET 컴파일된 사용자 지정 컨트롤을 만든 적이 있는 경우 이렇게 하려면 상당한 양의 레그워크가 필요하며 신중하게 처리해야 하는 미묘한 요소와 에지 케이스가 수반된다는 것을 알고 있습니다. 따라서 지금은 라디오 단추 열을 사용자 지정 DataControlField
클래스로 구현하는 것을 포기하고 TemplateField 옵션을 고수합니다. 향후 자습서에서는 사용자 지정 DataControlField
클래스를 만들고, 사용하고, 배포하는 방법을 살펴볼 수 있습니다.
4단계: 개별 페이지에 선택한 공급업체 제품 표시
사용자가 GridView 행을 선택한 후에는 선택한 공급업체 제품을 표시해야 합니다. 경우에 따라 이러한 제품을 별도의 페이지에 표시하고, 다른 경우에는 동일한 페이지에서 제품을 표시하는 것을 선호할 수 있습니다. 먼저 별도의 페이지에서 제품을 표시하는 방법을 살펴보겠습니다. 5단계에서는 GridView RadioButtonField.aspx
를 추가하여 선택한 공급업체 제품을 표시하는 방법을 살펴보겠습니다.
현재 페이지에 두 개의 버튼 웹 컨트롤 ListProducts
및 SendToProducts
가 있습니다.
SendToProducts
단추를 클릭하면 사용자를 ~/Filtering/ProductsForSupplierDetails.aspx
로 보내려고 합니다. 이 페이지는 두 페이지의 마스터/세부 정보 필터링 자습서에서 만들어졌으며 명명SupplierID
된 쿼리 문자열 필드를 통해 전달되는 공급자 SupplierID
의 제품을 표시합니다.
이 기능을 제공하려면 Button SendToProducts
이벤트에 대한 Click
이벤트 처리기를 만듭니다. 3단계에서 라디오 단추가 선택된 행의 인덱스를 반환하는 속성 SuppliersSelectedIndex
을(를) 추가했습니다. 해당 SupplierID
는 GridView의 DataKeys
컬렉션에서 검색할 수 있으며, ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
를 사용하여 사용자를 Response.Redirect("url")
로 보낼 수 있습니다.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End Sub
이 코드는 GridView에서 라디오 단추 중 하나를 선택하는 한 멋지게 작동합니다. 처음에 GridView에 라디오 버튼이 선택되어 있지 않은 상태에서 사용자가 SendToProducts
버튼을 클릭하면, SuppliersSelectedIndex
이(가) -1
이므로 예외가 발생하게 됩니다. 이는 -1
가 DataKeys
컬렉션의 인덱스 범위에서 벗어나기 때문입니다. 그러나 GridView의 첫 번째 라디오 단추를 처음에 선택하도록 3단계에서 설명한 대로 이벤트 처리기를 업데이트 RowCreated
하기로 결정한 경우에는 문제가 되지 않습니다.
SuppliersSelectedIndex
값을 -1
로 수용하기 위해, GridView 위의 페이지에 Label 웹 컨트롤을 추가하세요.
ID
속성을 ChooseSupplierMsg
로 설정하고, CssClass
속성을 Warning
로 설정하며, EnableViewState
및 Visible
속성을 False
로 설정하고, Text
속성을 표에서 공급자를 선택하세요. CSS 클래스 Warning
는 빨간색, 기울임꼴, 굵은 글꼴, 큰 글꼴로 텍스트를 표시하며 에 정의되어 있습니다 Styles.css
.
EnableViewState
및 Visible
속성을 False
으로 설정하면, Control의 Visible
속성이 프로그래밍 방식으로 True
으로 설정된 경우를 제외하고, Label은 렌더링되지 않습니다.
그림 13: GridView 위에 레이블 웹 컨트롤 추가(전체 크기 이미지를 보려면 클릭)
다음으로, Click
이벤트 처리기를 확장하여 ChooseSupplierMsg
가 0보다 작은 경우에는 SuppliersSelectedIndex
레이블을 표시하고, 그렇지 않으면 사용자를 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
로 리디렉션합니다.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
Else
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End If
End Sub
GridView에서 공급업체를 선택하기 전에 브라우저에서 페이지를 방문하고 단추를 클릭합니다 SendToProducts
. 그림 14와 같이 레이블이 ChooseSupplierMsg
표시됩니다. 다음으로 공급업체를 선택하고 단추를 클릭합니다 SendToProducts
. 그러면 선택한 공급업체에서 제공하는 제품이 나열된 페이지로 이동됩니다. 그림 15는 빅풋 양조장 공급업체가 선택된 ProductsForSupplierDetails.aspx
페이지를 보여줍니다.
그림 14: ChooseSupplierMsg
공급자가 선택되지 않은 경우 레이블이 표시됩니다(전체 크기 이미지를 보려면 클릭).
그림 15: 선택한 공급업체 제품이 표시됩니다 ProductsForSupplierDetails.aspx
(전체 크기 이미지를 보려면 클릭).
5단계: 동일한 페이지에 선택한 공급업체 제품 표시
4단계에서는 사용자를 다른 웹 페이지로 보내 선택한 공급업체 제품을 표시하는 방법을 알아보았습니다. 또는 선택한 공급업체 제품을 동일한 페이지에 표시할 수 있습니다. 이를 설명하기 위해 다른 GridView를 RadioButtonField.aspx
추가하여 선택한 공급업체 제품을 표시합니다.
공급업체가 선택된 후에만 제품의 이 GridView를 표시하도록 하려면 GridView 아래에 Suppliers
패널 웹 컨트롤을 추가하고 해당 ID
ProductsBySupplierPanel
Visible
속성을 False
로 설정합니다. 패널 내에서 선택한 공급업체에 대한 "제품" 텍스트를 추가하고, 이름이 ProductsBySupplier
인 GridView를 추가합니다. GridView의 스마트 태그에서 새 ObjectDataSource에 ProductsBySupplierDataSource
바인딩하도록 선택합니다.
그림 16: GridView를 ProductsBySupplier
새 ObjectDataSource에 바인딩(전체 크기 이미지를 보려면 클릭)
다음으로, 클래스를 사용하도록 ObjectDataSource를 구성합니다 ProductsBLL
. 선택한 공급업체에서 제공하는 제품만 검색하려고 하므로 ObjectDataSource에서 메서드를 호출 GetProductsBySupplierID(supplierID)
하여 해당 데이터를 검색하도록 지정합니다. UPDATE, INSERT 및 DELETE 탭의 드롭다운 목록에서 (없음)을 선택합니다.
그림 17: 메서드를 사용하도록 GetProductsBySupplierID(supplierID)
ObjectDataSource 구성(전체 크기 이미지를 보려면 클릭)
그림 18: UPDATE, INSERT 및 DELETE 탭에서 Drop-Down 목록을 (없음)으로 설정합니다(전체 크기 이미지를 보려면 클릭).
SELECT, UPDATE, INSERT 및 DELETE 탭을 구성한 후 다음을 클릭합니다. 메서드에 GetProductsBySupplierID(supplierID)
입력 매개 변수가 예상되므로 데이터 원본 만들기 마법사는 매개 변수 값의 원본을 지정하라는 메시지를 표시합니다.
매개 변수 값의 원본을 지정하는 몇 가지 옵션이 있습니다. 기본 Parameter 개체를 사용하고 ObjectDataSource SuppliersSelectedIndex
이벤트 DefaultValue
처리기의 Parameter Selecting
속성에 속성 값을 프로그래밍 방식으로 할당할 수 있습니다.
ObjectDataSource의 매개 변수 값 설정을 프로그래밍 방식으로 수행하는 방법을 상기하기 위해 해당 자습서를 참조하세요.
또는 ControlParameter를 사용하여 Suppliers
GridView의 SelectedValue
속성을 참조할 수 있습니다(그림 19 참조). GridView의 SelectedValue
속성은 속성에 DataKey
해당하는 값을 반환합니다SelectedIndex
. 이 옵션이 작동하려면 단추를 클릭할 때 SelectedIndex
GridView 속성을 ListProducts
선택한 행으로 프로그래밍 방식으로 설정해야 합니다. 추가 혜택으로, SelectedIndex
을(를) 설정하면 선택한 레코드가 SelectedRowStyle
테마(노란색 배경색)에 정의된 DataWebControls
을(를) 사용하게 됩니다.
그림 19: ControlParameter를 사용하여 GridView의 SelectedValue를 매개 변수 원본으로 지정합니다(전체 크기 이미지를 보려면 클릭).
마법사를 완료하면 Visual Studio에서 제품 데이터 필드에 대한 필드를 자동으로 추가합니다.
ProductName
, CategoryName
, UnitPrice
BoundFields를 제외한 모든 항목을 제거하고 HeaderText
속성을 Product, Category 및 Price로 변경하십시오. 해당 값이 UnitPrice
통화 형식으로 지정되도록 BoundField를 구성합니다. 이러한 변경을 수행한 후 Panel, GridView 및 ObjectDataSource의 선언적 태그는 다음과 같이 표시됩니다.
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
이 연습을 완료하기 위해서는, SelectedIndex
버튼이 클릭될 때 GridView의 SelectedSuppliersIndex
속성을 ProductsBySupplierPanel
로 설정하고, Panel의 Visible
속성을 True
로 설정해야 합니다. 이렇게 하려면 Button Web 컨트롤의 ListProducts
이벤트에 대한 Click
이벤트 처리기를 만들고 다음 코드를 추가합니다.
Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
Handles ListProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
ProductsBySupplierPanel.Visible = False
Else
' Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex
' Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = True
End If
End Sub
GridView ChooseSupplierMsg
에서 공급업체를 선택하지 않은 경우 레이블이 표시되고 패널이 ProductsBySupplierPanel
숨겨집니다. 그렇지 않으면 공급자가 선택된 ProductsBySupplierPanel
경우 해당 공급자가 표시되고 GridView의 SelectedIndex
속성이 업데이트됩니다.
그림 20은 Bigfoot 양조장 공급업체가 선택되고 페이지에 제품 표시 단추를 클릭한 후의 결과를 보여 줍니다.
그림 20: Bigfoot 양조장에서 제공하는 제품이 같은 페이지에 나열됩니다(전체 크기 이미지를 보려면 클릭).
요약
Master/Detail Using a Selectable Master GridView with a Details DetailView 자습서에서 설명한 대로 ShowSelectButton
속성이 True
로 설정된 CommandField를 사용하여 GridView에서 레코드를 선택할 수 있습니다. 그러나 CommandField는 해당 단추를 일반 누름 단추, 링크 또는 이미지로 표시합니다. 다른 행 선택 사용자 인터페이스는 각 GridView 행에 라디오 단추 또는 확인란을 제공하는 것입니다. 이 자습서에서는 라디오 단추 열을 추가하는 방법을 검토했습니다.
아쉽게도 라디오 버튼 열을 추가하는 것은 예상만큼 간단하거나 쉬운 일이 아닙니다. 단추를 클릭할 때 추가할 수 있는 기본 제공 RadioButtonField가 없으며 TemplateField 내에서 RadioButton 웹 컨트롤을 사용하면 고유한 문제 집합이 도입됩니다. 결국 이러한 인터페이스를 제공하려면 사용자 지정 DataControlField
클래스를 만들거나 이벤트 중에 RowCreated
적절한 HTML을 TemplateField에 삽입해야 합니다.
라디오 단추 열을 추가하는 방법을 살펴보면서 확인란 열을 추가하는 데 주의를 기울이겠습니다. 확인란의 열을 사용하여 사용자는 하나 이상의 GridView 행을 선택한 다음 선택한 모든 행(예: 웹 기반 전자 메일 클라이언트에서 전자 메일 집합을 선택한 다음 선택한 모든 전자 메일을 삭제하도록 선택)에 대해 작업을 수행할 수 있습니다. 다음 자습서에서는 이러한 열을 추가하는 방법을 살펴보겠습니다.
행복한 프로그래밍!
작성자 정보
7개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 연구해 왔습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그의 최신 책은 Sams Teach Yourself ASP.NET 2.0 in 24 Hours입니다. 그에게 mitchell@4GuysFromRolla.com으로 연락할 수 있습니다.
특별히 감사드립니다.
이 자습서 시리즈는 많은 유용한 검토자가 검토했습니다. 이 자습서의 수석 검토자는 David Suru였습니다. 예정된 MSDN 문서를 검토하는 데 관심이 있으신가요? 그렇다면 mitchell@4GuysFromRolla.com으로 메시지를 보내 주세요.