콘텐츠 페이지에서 컨트롤 ID 이름 지정(VB)Control ID Naming in Content Pages (VB)

Scott Mitchellby Scott Mitchell

코드 다운로드 또는 PDF 다운로드Download Code or Download PDF

ContentPlaceHolder 컨트롤이 명명 컨테이너 역할을 하 여 프로그래밍 방식으로 컨트롤을 사용 하기 어렵게 만드는 방법을 보여 줍니다 (FindControl를 통해).Illustrates how ContentPlaceHolder controls serve as a naming container and therefore make programmatically working with a control difficult (via FindControl). 이 문제와 해결 방법을 살펴봅니다.Looks at this issue and workarounds. 또한 결과 ClientID 값에 프로그래밍 방식으로 액세스 하는 방법을 설명 합니다.Also discusses how to programmatically access the resulting ClientID value.

소개Introduction

모든 ASP.NET 서버 컨트롤에는 컨트롤을 고유 하 게 식별 하는 ID 속성이 포함 되며, 코드를 사용 하는 클래스에서 프로그래밍 방식으로 컨트롤에 액세스 하는 방법입니다.All ASP.NET server controls include an ID property that uniquely identifies the control and is the means by which the control is programmatically accessed in the code-behind class. 마찬가지로 HTML 문서의 요소는 요소를 고유 하 게 식별 하는 id 특성을 포함할 수 있습니다. 이러한 id 값은 종종 클라이언트 쪽 스크립트에서 특정 HTML 요소를 프로그래밍 방식으로 참조 하는 데 사용 됩니다.Similarly, the elements in an HTML document may include an id attribute that uniquely identifies the element; these id values are often used in client-side script to programmatically reference a particular HTML element. 이 경우 ASP.NET 서버 컨트롤이 HTML로 렌더링 될 때 ID 값이 렌더링 된 HTML 요소의 id 값으로 사용 된다고 가정할 수 있습니다.Given this, you may assume that when an ASP.NET server control is rendered into HTML, its ID value is used as the id value of the rendered HTML element. 특정 상황에서는 렌더링 된 태그에서 단일 ID 값이 포함 된 단일 컨트롤이 여러 번 나타날 수 있기 때문에이는 반드시 그럴 필요는 없습니다.This is not necessarily the case because in certain circumstances a single control with a single ID value may appear multiple times in the rendered markup. ID 값이 ProductName인 레이블 웹 컨트롤과 함께 Templatefield로 변환를 포함 하는 GridView 컨트롤을 사용 합니다.Consider a GridView control that includes a TemplateField with a Label Web control with an ID value of ProductName. GridView가 런타임에 데이터 원본에 바인딩되면이 레이블은 모든 GridView 행에 대해 한 번씩 반복 됩니다.When the GridView is bound to its data source at runtime, this Label is repeated once for every GridView row. 렌더링 된 각 레이블에는 고유한 id 값이 필요 합니다.Each rendered Label needs a unique id value.

이러한 시나리오를 처리 하기 위해 ASP.NET를 사용 하면 특정 컨트롤을 명명 컨테이너로 표시할 수 있습니다.To handle such scenarios, ASP.NET allows certain controls to be denoted as naming containers. 명명 컨테이너는 새 ID 네임 스페이스로 사용 됩니다.A naming container serves as a new ID namespace. 명명 컨테이너 내에 표시 되는 모든 서버 컨트롤에는 명명 컨테이너 컨트롤의 ID 접두사로 붙는 렌더링 된 id 값이 있습니다.Any server controls that appear within the naming container have their rendered id value prefixed with the ID of the naming container control. 예를 들어 GridViewGridViewRow 클래스는 둘 다 명명 컨테이너입니다.For example, the GridView and GridViewRow classes are both naming containers. 따라서 ID ProductName를 사용 하 여 GridView Templatefield로 변환에 정의 된 레이블 컨트롤에는 GridViewID_GridViewRowID_ProductName의 렌더링 된 id 값이 지정 됩니다.Consequently, a Label control defined in a GridView TemplateField with ID ProductName is given a rendered id value of GridViewID_GridViewRowID_ProductName. GridViewRowID 는 각 GridView 행에 대해 고유 하기 때문에 결과 id 값은 고유 합니다.Because GridViewRowID is unique for each GridView row, the resulting id values are unique.

Note

INamingContainer 인터페이스 는 특정 ASP.NET 서버 컨트롤이 명명 컨테이너 역할을 하도록 지정 하는 데 사용 됩니다.The INamingContainer interface is used to indicate that a particular ASP.NET server control should function as a naming container. INamingContainer 인터페이스는 서버 컨트롤에서 구현 해야 하는 메서드를 검사 하지 않습니다. 대신 마커로 사용 됩니다.The INamingContainer interface does not spell out any methods that the server control must implement; rather, it's used as a marker. 렌더링 된 태그를 생성할 때 컨트롤이이 인터페이스를 구현 하는 경우 ASP.NET 엔진은 자동으로 해당 ID 값에 해당 하위의 렌더링 된 id 특성 값에 접두사를 붙입니다.In generating the rendered markup, if a control implements this interface then the ASP.NET engine automatically prefixes its ID value to its descendents' rendered id attribute values. 이 프로세스는 2 단계에 자세히 설명 되어 있습니다.This process is discussed in more detail in Step 2.

명명 컨테이너는 렌더링 된 id 특성 값을 변경할 뿐만 아니라 컨트롤을 프로그래밍 방식으로 ASP.NET 페이지의 코드 숨김이 클래스에서 참조할 수 있는 방법에도 영향을 줍니다.Naming containers not only change the rendered id attribute value, but also affect how the control may be programmatically referenced from the ASP.NET page's code-behind class. FindControl("controlID") 메서드는 일반적으로 웹 컨트롤을 프로그래밍 방식으로 참조 하는 데 사용 됩니다.The FindControl("controlID") method is commonly used to programmatically reference a Web control. 그러나 FindControl은 명명 컨테이너를 통해 침투 하지 않습니다.However, FindControl does not penetrate through naming containers. 따라서 GridView 또는 다른 명명 컨테이너 내의 컨트롤을 참조 하는 데 Page.FindControl 메서드를 직접 사용할 수 없습니다.Consequently, you cannot directly use the Page.FindControl method to reference controls within a GridView or other naming container.

Surmised 수 있듯이 마스터 페이지와 ContentPlaceHolders 표시자는 모두 명명 컨테이너로 구현 됩니다.As you may have surmised, master pages and ContentPlaceHolders are both implemented as naming containers. 이 자습서에서는 마스터 페이지가 FindControl를 사용 하 여 콘텐츠 페이지 내에서 프로그래밍 방식으로 웹 컨트롤을 참조 하는 id 값 및 방법에 영향을 줍니다.In this tutorial we examine how master pages affect HTML element id values and ways to programmatically reference Web controls within a content page using FindControl.

1 단계: 새 ASP.NET 페이지 추가Step 1: Adding a New ASP.NET Page

이 자습서에서 설명 하는 개념을 설명 하기 위해 웹 사이트에 새 ASP.NET 페이지를 추가 해 보겠습니다.To demonstrate the concepts discussed in this tutorial, let's add a new ASP.NET page to our website. 루트 폴더에 IDIssues.aspx 라는 새 콘텐츠 페이지를 만들어 Site.master 마스터 페이지에 바인딩합니다.Create a new content page named IDIssues.aspx in the root folder, binding it to the Site.master master page.

콘텐츠 페이지 IDIssues를 루트 폴더에 추가 합니다.

그림 01: 루트 폴더에 IDIssues.aspx 콘텐츠 페이지 추가Figure 01: Add the Content Page IDIssues.aspx to the Root Folder

Visual Studio는 각 마스터 페이지의 4 개 ContentPlaceHolders 표시자에 대 한 콘텐츠 컨트롤을 자동으로 만듭니다.Visual Studio automatically creates a Content control for each of the master page's four ContentPlaceHolders. 여러 ContentPlaceHolders 표시자 및 기본 콘텐츠 자습서에 설명 된 대로 콘텐츠 컨트롤이 표시 되지 않는 경우 마스터 페이지의 기본 ContentPlaceHolder 콘텐츠를 대신 내보냅니다.As noted in the Multiple ContentPlaceHolders and Default Content tutorial, if a Content control is not present the master page's default ContentPlaceHolder content is emitted instead. QuickLoginUILeftColumnContent ContentPlaceHolders 표시자에는이 페이지에 적합 한 기본 태그가 포함 되어 있으므로 IDIssues.aspx에서 해당 콘텐츠 컨트롤을 제거 하세요.Because the QuickLoginUI and LeftColumnContent ContentPlaceHolders contain suitable default markup for this page, go ahead and remove their corresponding Content controls from IDIssues.aspx. 이 시점에서 콘텐츠 페이지의 선언 태그는 다음과 같습니다.At this point, the content page's declarative markup should look like the following:

<%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="IDIssues.aspx.vb" Inherits="IDIssues" Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>

마스터 페이지에서 제목, 메타 태그 및 기타 HTML 헤더 지정 자습서에서 명시적으로 설정 하지 않은 경우 페이지의 제목을 자동으로 구성 하는 사용자 지정 기본 페이지 클래스 (BasePage)를 만들었습니다.In the Specifying the Title, Meta Tags, and Other HTML Headers in the Master Page tutorial we created a custom base page class (BasePage) that automatically configures the page's title if it is not explicitly set. IDIssues.aspx 페이지에서이 기능을 사용 하려면 페이지의 코드 숨김이 BasePage 클래스 (System.Web.UI.Page대신)에서 파생 되어야 합니다.For the IDIssues.aspx page to employ this functionality, the page's code-behind class must derive from the BasePage class (instead of System.Web.UI.Page). 다음과 같이 코드를 정의 하는 클래스의 정의를 수정 합니다.Modify the code-behind class's definition so that it looks like the following:

Partial Class IDIssues
 Inherits BasePage

End Class

마지막으로이 새 단원에 대 한 항목을 포함 하도록 Web.sitemap 파일을 업데이트 합니다.Finally, update the Web.sitemap file to include an entry for this new lesson. <siteMapNode> 요소를 추가 하 고 titleurl 특성을 각각 "Control ID 명명 문제" 및 ~/IDIssues.aspx로 설정 합니다.Add a <siteMapNode> element and set its title and url attributes to "Control ID Naming Issues" and ~/IDIssues.aspx, respectively. 이러한 추가 작업을 수행한 후 Web.sitemap 파일의 태그가 다음과 같이 표시 됩니다.After making this addition your Web.sitemap file's markup should look similar to the following:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
 <siteMapNode url="~/Default.aspx" title="Home">
 <siteMapNode url="~/About.aspx" title="About the Author" />
 <siteMapNode url="~/MultipleContentPlaceHolders.aspx" title="Using Multiple ContentPlaceHolder Controls" />
 <siteMapNode url="~/Admin/Default.aspx" title="Rebasing URLs" />
 <siteMapNode url="~/IDIssues.aspx" title="Control ID Naming Issues" />
 </siteMapNode>
</siteMap>

그림 2에 나와 있는 것 처럼 Web.sitemap의 새 사이트 맵 항목이 왼쪽 열에 있는 단원 섹션에 즉시 반영 됩니다.As Figure 2 illustrates, the new site map entry in Web.sitemap is immediately reflected in the Lessons section in the left column.

이제 단원 섹션에 "컨트롤 ID 명명 문제에 대 한 링크가 포함 되어"

그림 02: 단원 섹션에는 이제 "컨트롤 ID 명명 문제"에 대 한 링크가 포함 되어 있습니다.Figure 02: The Lessons Section Now Includes a Link to "Control ID Naming Issues"

2 단계: 렌더링 된ID변경 내용 검사Step 2: Examining the RenderedIDChanges

ASP.NET 엔진이 서버 컨트롤의 렌더링 된 id 값에 대해 수행 하는 수정 사항을 더 잘 이해 하려면 IDIssues.aspx 페이지에 몇 가지 웹 컨트롤을 추가한 다음 브라우저에 전송 된 렌더링 된 태그를 확인 합니다.To better understand the modifications the ASP.NET engine makes to the rendered id values of server controls, let's add a few Web controls to the IDIssues.aspx page and then view the rendered markup sent to the browser. 특히 텍스트를 입력 하 고 텍스트 상자에 텍스트를 입력 하십시오.Specifically, type in the text "Please enter your age:" followed by a TextBox Web control. 페이지의 아래쪽에서 단추 웹 컨트롤과 Label 웹 컨트롤을 추가 합니다.Further down on the page add a Button Web control and a Label Web control. 텍스트 상자의 IDColumns 속성을 각각 Age 및 3으로 설정 합니다.Set the TextBox's ID and Columns properties to Age and 3, respectively. 단추의 TextID 속성을 "Submit"로 설정 하 고 SubmitButton합니다.Set the Button's Text and ID properties to "Submit" and SubmitButton. 레이블의 Text 속성을 지우고 IDResults로 설정 합니다.Clear out the Label's Text property and set its ID to Results.

이 시점에서 콘텐츠 컨트롤의 선언 태그는 다음과 유사 하 게 표시 됩니다.At this point your Content control's declarative markup should look similar to the following:

<p>
 Please enter your age:
 <asp:TextBox ID="Age" Columns="3" runat="server"></asp:TextBox>
</p>
<p>
 <asp:Button ID="SubmitButton" runat="server" Text="Submit" />
</p>
<p>
 <asp:Label ID="Results" runat="server"></asp:Label>
</p>

그림 3에서는 Visual Studio의 디자이너를 통해 볼 때의 페이지를 보여 줍니다.Figure 3 shows the page when viewed through Visual Studio's designer.

페이지에는 텍스트 상자, 단추 및 레이블의 세 가지 웹 컨트롤이 포함 합니다.The Page Includes Three Web Controls: a TextBox, Button, and Label

그림 03: 페이지에는 텍스트 상자, 단추 및 레이블의 세 가지 웹 컨트롤 (전체 크기의 이미지를 보려면 클릭)이 포함 되어 있습니다.Figure 03: The Page Includes Three Web Controls: a TextBox, Button, and Label (Click to view full-size image)

브라우저를 통해 페이지를 방문 하 여 HTML 소스를 봅니다.Visit the page through a browser and then view the HTML source. 아래 태그가 보여 주는 것 처럼 텍스트 상자, 단추 및 레이블 웹 컨트롤에 대 한 HTML 요소의 id 값은 웹 컨트롤의 ID 값과 페이지의 명명 컨테이너에 대 한 ID 값의 조합입니다.As the markup below shows, the id values of the HTML elements for the TextBox, Button, and Label Web controls are a combination of the ID values of the Web controls and the ID values of the naming containers in the page.

<p>
 Please enter your age:
 <input name="ctl00$MainContent$Age" type="text" size="3" id="ctl00_MainContent_Age" />
</p>
<p>

 <input type="submit" name="ctl00$MainContent$SubmitButton" value="Submit" id="ctl00_MainContent_SubmitButton" />
</p>
<p>
 <span id="ctl00_MainContent_Results"></span>
</p>

이 자습서의 앞부분에서 설명한 것 처럼 마스터 페이지와 ContentPlaceHolders 표시자는 모두 명명 컨테이너 역할을 합니다.As noted earlier in this tutorial, both the master page and its ContentPlaceHolders serve as naming containers. 따라서 둘 다 렌더링 된 ID 값을 중첩 된 컨트롤에 적용 합니다.Consequently, both contribute the rendered ID values of their nested controls. 텍스트 상자의 id 특성을 사용 합니다 (예: ctl00_MainContent_Age).Take the TextBox's id attribute, for instance: ctl00_MainContent_Age. TextBox 컨트롤의 ID 값이 Age되었음을 기억 합니다.Recall that the TextBox control's ID value was Age. ContentPlaceHolder 컨트롤의 IDMainContent접두사가 붙습니다.This is prefixed with its ContentPlaceHolder control's ID value, MainContent. 또한이 값에는 마스터 페이지의 IDctl00접두사가 붙습니다.Furthermore, this value is prefixed with the master page's ID value, ctl00. Net 효과는 마스터 페이지의 ID 값, ContentPlaceHolder 컨트롤 및 텍스트 상자 자체로 구성 된 id 특성 값입니다.The net effect is an id attribute value consisting of the ID values of the master page, the ContentPlaceHolder control, and the TextBox itself.

그림 4에서는이 동작을 보여 줍니다.Figure 4 illustrates this behavior. Age 텍스트 상자의 렌더링 된 id를 확인 하려면 TextBox 컨트롤의 IDAge를 사용 하 여 시작 합니다.To determine the rendered id of the Age TextBox, start with the ID value of the TextBox control, Age. 다음으로 컨트롤 계층 구조를 사용 합니다.Next, work your way up the control hierarchy. 각 명명 컨테이너 (복숭아색 색이 있는 노드)에서 현재 렌더링 된 id 명명 컨테이너의 id접두사로 지정 합니다.At each naming container (those nodes with a peach color), prefix the current rendered id with the naming container's id.

렌더링 된 id 특성은 명명 컨테이너의 ID 값을 기반으로 합니다.

그림 04: 렌더링 된 id 특성은 명명 컨테이너의 ID 값을 기반으로 합니다.Figure 04: The Rendered id Attributes are Based On the ID Values of the Naming Containers

Note

앞서 설명 했 듯이 렌더링 된 id 특성의 ctl00 부분은 마스터 페이지의 ID 값을 구성 하지만이 ID 값의 출처를 궁금할 수 있습니다.As we discussed, the ctl00 portion of the rendered id attribute constitutes the ID value of the master page, but you may be wondering how this ID value came about. 마스터 또는 콘텐츠 페이지에서 아무 곳 이나 지정 하지 않았습니다.We did not specify it anywhere in our master or content page. ASP.NET 페이지의 대부분 서버 컨트롤은 페이지의 선언적 태그를 통해 명시적으로 추가 됩니다.Most server controls in an ASP.NET page are added explicitly through the page's declarative markup. MainContent ContentPlaceHolder 컨트롤이 Site.master의 태그에 명시적으로 지정 되었습니다. Age 텍스트 상자가 태그 IDIssues.aspx정의 되었습니다.The MainContent ContentPlaceHolder control was explicitly specified in the markup of Site.master; the Age TextBox was defined IDIssues.aspx's markup. 속성 창 또는 선언적 구문을 통해 이러한 컨트롤 형식에 대 한 ID 값을 지정할 수 있습니다.We can specify the ID values for these types of controls through the Properties window or from the declarative syntax. 마스터 페이지 자체와 같은 다른 컨트롤은 선언적 태그에 정의 되어 있지 않습니다.Other controls, like the master page itself, are not defined in the declarative markup. 따라서 해당 ID 값이 자동으로 생성 되어야 합니다.Consequently, their ID values must be automatically generated for us. ASP.NET 엔진은 Id가 명시적으로 설정 되지 않은 컨트롤에 대해 런타임에 ID 값을 설정 합니다.The ASP.NET engine sets the ID values at runtime for those controls whose IDs have not been explicitly set. 명명 패턴 ctlXX를 사용 합니다. 여기서 XX 는 순차적으로 늘어나는 정수 값입니다.It uses the naming pattern ctlXX, where XX is a sequentially increasing integer value.

마스터 페이지 자체가 명명 컨테이너 역할을 하기 때문에 마스터 페이지에 정의 된 웹 컨트롤은 특성 값 id 렌더링 된 것으로 변경 되었습니다.Because the master page itself serves as a naming container, the Web controls defined in the master page also have altered rendered id attribute values. 예를 들어 마스터 페이지를 사용 하 여 사이트 전체 레이아웃 만들기 자습서에서 마스터 페이지에 추가한 DisplayDate 레이블은 다음과 같이 렌더링 된 태그를 가집니다.For example, the DisplayDate Label we added to the master page in the Creating a Site-Wide Layout with Master Pages tutorial has the following rendered markup:

<span id="ctl00_DateDisplay">current date</span>

id 특성에는 마스터 페이지의 ID 값 (ctl00)과 레이블 웹 컨트롤 (DateDisplay)의 ID 값이 모두 포함 되어 있습니다.Note that the id attribute includes both the master page's ID value (ctl00) and the ID value of the Label Web control (DateDisplay).

3 단계:FindControl를 통해 프로그래밍 방식으로 웹 컨트롤 참조Step 3: Programmatically Referencing Web Controls viaFindControl

모든 ASP.NET 서버 컨트롤에는 컨트롤의 하위 항목에서 controlID라는 컨트롤을 검색 하는 FindControl("controlID") 메서드가 포함 되어 있습니다.Every ASP.NET server control includes a FindControl("controlID") method that searches the control's descendents for a control named controlID. 이러한 컨트롤이 있는 경우 반환 됩니다. 일치 하는 컨트롤이 없으면 FindControl에서 Nothing를 반환 합니다.If such a control is found, it is returned; if no matching control is found, FindControl returns Nothing.

FindControl은 컨트롤에 액세스 해야 하지만 직접 참조 하지 않는 시나리오에서 유용 합니다.FindControl is useful in scenarios where you need to access a control but you don't have a direct reference to it. 예를 들어 GridView와 같은 데이터 웹 컨트롤을 사용할 때 GridView의 필드 내에 있는 컨트롤은 선언적 구문에서 한 번 정의 되지만 런타임에는 각 GridView 행에 대해 컨트롤의 인스턴스가 생성 됩니다.When working with data Web controls like the GridView, for example, the controls within the GridView's fields are defined once in the declarative syntax, but at runtime an instance of the control is created for each GridView row. 따라서 런타임에 생성 된 컨트롤은 있지만 코드 숨김이 아닌 클래스에서 직접 참조를 사용할 수 없습니다.Consequently, the controls generated at runtime exist, but we do not have a direct reference available from the code-behind class. 따라서 FindControl를 사용 하 여 GridView의 필드 내에서 특정 컨트롤을 프로그래밍 방식으로 작업 해야 합니다.As a result we need to use FindControl to programmatically work with a specific control within the GridView's fields. FindControl 사용 하 여 데이터 웹 컨트롤의 템플릿 내에서 컨트롤에 액세스 하는 방법에 대 한 자세한 내용은 데이터를 기반으로 하는 사용자 지정 서식 지정을 참조 하세요. 이 시나리오는 웹 컨트롤을 웹 폼에 동적으로 추가 하는 경우에 발생 합니다 .이 항목에서는 Dynamic Data 항목 사용자 인터페이스 만들기에 설명 되어 있습니다.(For more information on using FindControl to access the controls within a data Web control's templates, see Custom Formatting Based Upon Data.) This same scenario occurs when dynamically adding Web controls to a Web Form, a topic discussed in Creating Dynamic Data Entry User Interfaces.

FindControl 메서드를 사용 하 여 콘텐츠 페이지에서 컨트롤을 검색 하는 방법을 보여 주려면 SubmitButtonClick 이벤트에 대 한 이벤트 처리기를 만듭니다.To illustrate using the FindControl method to search for controls within a content page, create an event handler for the SubmitButton's Click event. 이벤트 처리기에서 다음 코드를 추가 합니다 .이 코드는 FindControl 메서드를 사용 하 여 프로그래밍 방식으로 Age TextBox 및 Results 레이블을 참조 하 고 사용자의 입력에 따라 Results에 메시지를 표시 합니다.In the event handler, add the following code, which programmatically references the Age TextBox and Results Label using the FindControl method and then displays a message in Results based on the user's input.

Note

물론이 예제에서는 FindControl를 사용 하 여 레이블 및 TextBox 컨트롤을 참조할 필요가 없습니다.Of course, we don't need to use FindControl to reference the Label and TextBox controls for this example. ID 속성 값을 통해 직접 참조할 수 있습니다.We could reference them directly via their ID property values. 여기서 FindControl를 사용 하 여 콘텐츠 페이지에서 FindControl를 사용할 때 발생 하는 상황을 설명 합니다.I use FindControl here to illustrate what happens when using FindControl from a content page.

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim ResultsLabel As Label = CType(FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(Page.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

FindControl 메서드를 호출 하는 데 사용 되는 구문은 SubmitButton_Click처음 두 줄에 약간 차이가 있지만 의미 체계는 동일 합니다.While the syntax used to call the FindControl method differs slightly in the first two lines of SubmitButton_Click, they are semantically equivalent. 모든 ASP.NET 서버 컨트롤에 FindControl 메서드가 포함 되어 있음을 기억 하세요.Recall that all ASP.NET server controls include a FindControl method. 여기에는 모든 ASP.NET 코드 숨김이 클래스에서 파생 되어야 하는 Page 클래스가 포함 됩니다.This includes the Page class, from which all ASP.NET code-behind classes must derive from. 따라서 FindControl("controlID")를 호출 하는 것은 Page.FindControl("controlID")호출 하는 것과 같으며,이 경우에는 코드 숨김이 나 사용자 지정 기본 클래스에서 FindControl 메서드를 재정의 하지 않은 것으로 가정 합니다.Therefore, calling FindControl("controlID") is equivalent to calling Page.FindControl("controlID"), assuming you haven't overridden the FindControl method in your code-behind class or in a custom base class.

이 코드를 입력 한 후 브라우저를 통해 IDIssues.aspx 페이지를 방문 하 고 나이를 입력 한 후 "제출" 단추를 클릭 합니다.After entering this code, visit the IDIssues.aspx page through a browser, enter your age, and click the "Submit" button. "제출" 단추를 클릭 하면 NullReferenceException 발생 합니다 (그림 5 참조).Upon clicking the "Submit" button a NullReferenceException is raised (see Figure 5).

NullReferenceException이 발생 A NullReferenceException is Raised

그림 05: NullReferenceException 발생 (전체 크기 이미지를 보려면 클릭)Figure 05: A NullReferenceException is Raised (Click to view full-size image)

SubmitButton_Click 이벤트 처리기에 중단점을 설정 하면 FindControl에 대 한 두 호출이 모두 Nothing을 반환 하는 것을 볼 수 있습니다.If you set a breakpoint in the SubmitButton_Click event handler you will see that both calls to FindControl return Nothing. Age TextBox의 Text 속성에 액세스 하려고 하면 NullReferenceException 발생 합니다.The NullReferenceException is raised when we attempt to access the Age TextBox's Text property.

문제는 Control.FindControl 동일한 명명 컨테이너에 있는 컨트롤의 하위 항목만 검색 하는 것입니다.The problem is that Control.FindControl only searches Control's descendents that are in the same naming container. 마스터 페이지는 새 명명 컨테이너를 구성 하기 때문에 Page.FindControl("controlID")를 호출 하면 마스터 페이지 개체가 ctl00되지 않습니다.Because the master page constitutes a new naming container, a call to Page.FindControl("controlID") never permeates the master page object ctl00. Page 개체를 ctl00마스터 페이지 개체의 부모로 표시 하는 컨트롤 계층 구조를 보려면 그림 4로 다시 참조 하세요. 따라서 Results 레이블 및 Age TextBox를 찾을 수 없으며 ResultsLabelAgeTextBoxNothing값이 할당 됩니다.(Refer back to Figure 4 to view the control hierarchy, which shows the Page object as the parent of the master page object ctl00.) Therefore, the Results Label and Age TextBox are not found and ResultsLabel and AgeTextBox are assigned values of Nothing.

이 문제에 대 한 두 가지 해결 방법이 있습니다. 즉, 한 번에 하나의 명명 컨테이너를 적절 한 컨트롤로 드릴 다운할 수 있습니다. 또는 컨테이너의 명명을 permeates 하는 고유한 FindControl 메서드를 만들 수 있습니다.There are two workarounds to this challenge: we can drill down, one naming container at a time, to the appropriate control; or we can create our own FindControl method that permeates naming containers. 이러한 각 옵션을 살펴보겠습니다.Let's examine each of these options.

적절 한 명명 컨테이너를 드릴업 합니다.Drilling Into the Appropriate Naming Container

FindControl를 사용 하 여 Results 레이블 또는 Age 텍스트 상자를 참조 하려면 동일한 명명 컨테이너의 상위 컨트롤에서 FindControl를 호출 해야 합니다.To use FindControl to reference the Results Label or Age TextBox, we need to call FindControl from an ancestor control in the same naming container. 그림 4에 표시 된 것 처럼 MainContent ContentPlaceHolder 컨트롤은 동일한 명명 컨테이너에 있는 Results 또는 Age의 유일한 상위 항목입니다.As Figure 4 showed, the MainContent ContentPlaceHolder control is the only ancestor of Results or Age that is within the same naming container. 즉, 아래 코드 조각에 표시 된 것 처럼 MainContent 컨트롤에서 FindControl 메서드를 호출 하면 Results 또는 Age 컨트롤에 대 한 참조가 올바르게 반환 됩니다.In other words, calling the FindControl method from the MainContent control, as shown in the code snippet below, correctly returns a reference to the Results or Age controls.

Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

그러나 ContentPlaceHolder가 마스터 페이지에 정의 되어 있기 때문에 위의 구문을 사용 하 여 콘텐츠 페이지의 코드 숨김이 ContentPlaceHolder에서 MainContent를 사용할 수 없습니다.However, we cannot work with the MainContent ContentPlaceHolder from our content page's code-behind class using the above syntax because the ContentPlaceHolder is defined in the master page. 대신 FindControl를 사용 하 여 MainContent에 대 한 참조를 가져와야 합니다.Instead, we have to use FindControl to get a reference to MainContent. SubmitButton_Click 이벤트 처리기의 코드를 다음과 같이 수정 합니다.Replace the code in the SubmitButton_Click event handler with the following modifications:

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim MainContent As ContentPlaceHolder = CType(FindControl("MainContent"), ContentPlaceHolder)

 Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

브라우저를 통해 페이지를 방문 하는 경우 나이를 입력 하 고 "제출" 단추를 클릭 하면 NullReferenceException 발생 합니다.If you visit the page through a browser, enter your age, and click the "Submit" button, a NullReferenceException is raised. SubmitButton_Click 이벤트 처리기에 중단점을 설정 하면 MainContent 개체의 FindControl 메서드를 호출 하려고 할 때이 예외가 발생 하는 것을 볼 수 있습니다.If you set a breakpoint in the SubmitButton_Click event handler you will see that this exception occurs when attempting to call the MainContent object's FindControl method. FindControl 메서드가 "MainContent" 라는 개체를 찾을 수 없기 때문에 MainContent 개체는 Nothing와 같습니다.The MainContent object is equal to Nothing because the FindControl method cannot locate an object named "MainContent". 기본적인 이유는 Results 레이블 및 Age TextBox 컨트롤과 동일 합니다. FindControl는 컨트롤 계층 구조의 맨 위에서 검색을 시작 하 고 명명 컨테이너를 통과 하지 않지만 MainContent ContentPlaceHolder는 명명 컨테이너인 마스터 페이지 내에 있습니다.The underlying reason is the same as with the Results Label and Age TextBox controls: FindControl starts its search from the top of the control hierarchy and does not penetrate naming containers, but the MainContent ContentPlaceHolder is within the master page, which is a naming container.

FindControl를 사용 하 여 MainContent에 대 한 참조를 가져오려면 먼저 마스터 페이지 컨트롤에 대 한 참조가 필요 합니다.Before we can use FindControl to get a reference to MainContent, we first need a reference to the master page control. 마스터 페이지에 대 한 참조가 있으면 FindControl를 통해 MainContent ContentPlaceHolder에 대 한 참조를 가져올 수 있습니다. 여기서는 FindControl을 사용 하 여 Results 레이블 및 Age 텍스트 상자에 대 한 참조를 다시 사용할 수 있습니다.Once we have a reference to the master page we can get a reference to the MainContent ContentPlaceHolder via FindControl and, from there, references to the Results Label and Age TextBox (again, through using FindControl). 그러나 마스터 페이지에 대 한 참조는 어떻게 얻을 수 있나요?But how do we get a reference to the master page? 렌더링 된 태그에서 id 특성을 검사 하 여 마스터 페이지의 ID 값이 ctl00있음을 분명히 알 수 있습니다.By inspecting the id attributes in the rendered markup it's evident that the master page's ID value is ctl00. 따라서 Page.FindControl("ctl00")를 사용 하 여 마스터 페이지에 대 한 참조를 가져온 다음 해당 개체를 사용 하 여 MainContent에 대 한 참조를 가져올 수 있습니다.Therefore, we could use Page.FindControl("ctl00") to get a reference to the master page, then use that object to get a reference to MainContent, and so on. 다음 코드 조각에서는이 논리를 보여 줍니다.The following snippet illustrates this logic:

'Get a reference to the master page
Dim ctl00 As MasterPage = CType(FindControl("ctl00"), MasterPage)

'Get a reference to the ContentPlaceHolder
Dim MainContent As ContentPlaceHolder = CType(ctl00.FindControl("MainContent"), ContentPlaceHolder)

'Reference the Label and TextBox controls
Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

이 코드는 분명히 작동 하지만 마스터 페이지의 자동 생성 ID 항상 ctl00되는 것으로 가정 합니다.While this code will certainly work, it assumes that the master page's autogenerated ID will always be ctl00. 자동 생성 된 값에 대해 가정 하는 것은 좋지 않습니다.It's never a good idea to make assumptions about autogenerated values.

다행히 마스터 페이지에 대 한 참조는 Page 클래스의 Master 속성을 통해 액세스할 수 있습니다.Fortunately, a reference to the master page is accessible through the Page class's Master property. 따라서 MainContent ContentPlaceHolder에 액세스 하기 위해 FindControl("ctl00")를 사용 하 여 마스터 페이지의 참조를 가져오는 대신 Page.Master.FindControl("MainContent")를 사용할 수 있습니다.Therefore, instead of having to use FindControl("ctl00") to get a reference of the master page in order to access the MainContent ContentPlaceHolder, we can instead use Page.Master.FindControl("MainContent"). 다음 코드를 사용 하 여 SubmitButton_Click 이벤트 처리기를 업데이트 합니다.Update the SubmitButton_Click event handler with the following code:

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 'Get a reference to the ContentPlaceHolder
 Dim MainContent As ContentPlaceHolder = CType(Page.Master.FindControl("MainContent"), ContentPlaceHolder)

 'Reference the Label and TextBox controls
 Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

이번에는 브라우저를 통해 페이지를 방문 하 고 나이를 입력 한 다음 "제출" 단추를 클릭 하면 예상 대로 Results 레이블에 메시지가 표시 됩니다.This time, visiting the page through a browser, entering your age, and clicking the "Submit" button displays the message in the Results Label, as expected.

사용자의 나이가 레이블에 표시 되는 The User's Age is Displayed in the Label

그림 06: 사용자의 나이가 레이블에 표시 됩니다 (전체 크기 이미지를 보려면 클릭).Figure 06: The User's Age is Displayed in the Label (Click to view full-size image)

이름 지정 컨테이너를 통해 재귀적으로 검색Recursively Searching Through Naming Containers

이전 코드 예제에서 마스터 페이지의 MainContent ContentPlaceHolder 컨트롤을 참조 하 고 MainContent에서 Results 레이블 및 Age TextBox 컨트롤을 참조 하는 이유는 Control.FindControl 메서드가 컨트롤의 명명 컨테이너 내 에서만 검색 하기 때문입니다.The reason the previous code example referenced the MainContent ContentPlaceHolder control from the master page, and then the Results Label and Age TextBox controls from MainContent, is because the Control.FindControl method only searches within Control's naming container. 서로 다른 두 명명 컨테이너의 두 컨트롤에 동일한 ID 값이 있을 수 있기 때문에 명명 컨테이너 내에 FindControl을 유지 하는 것은 대부분의 시나리오에서 유용 합니다.Having FindControl stay within the naming container makes sense in most scenarios because two controls in two different naming containers may have the same ID values. 해당 템플릿 필드 중 하나에 ProductName 이라는 레이블 웹 컨트롤을 정의 하는 GridView의 경우를 고려 합니다.Consider the case of a GridView that defines a Label Web control named ProductName within one of its TemplateFields. 런타임에 데이터를 GridView에 바인딩하면 각 GridView 행에 대해 ProductName 레이블이 생성 됩니다.When the data is bound to the GridView at runtime, a ProductName Label is created for each GridView row. FindControl 모든 명명 컨테이너를 검색 하 고 Page.FindControl("ProductName")를 호출한 경우 FindControl에서 반환 해야 하는 레이블 인스턴스는 무엇 인가요?If FindControl searched through all naming containers and we called Page.FindControl("ProductName"), what Label instance should the FindControl return? 첫 번째 GridView 행의 ProductName 레이블이 있나요?The ProductName Label in the first GridView row? 마지막 행에 있는 항목The one in the last row?

Control.FindControl 검색을 사용 하면 대부분의 경우 컨트롤의 명명 컨테이너를 사용 하는 것이 좋습니다.So having Control.FindControl search just Control's naming container makes sense in most cases. 그러나 모든 명명 컨테이너에서 고유한 ID를가지고 있으며 컨트롤 계층 구조에서 각 명명 컨테이너를 참조 하 여 컨트롤에 액세스할 필요가 없도록 하는 것과 같은 다른 경우가 있습니다.But there are other cases, such as the one facing us, where we have a unique ID across all naming containers and want to avoid having to meticulously reference each naming container in the control hierarchy to access a control. 모든 명명 컨테이너를 재귀적으로 검색 하는 FindControl variant를 사용 하는 것도 좋습니다.Having a FindControl variant that recursively searches all naming containers makes sense, too. 아쉽게도 이러한 메서드는 .NET Framework에 포함 되지 않습니다.Unfortunately, the .NET Framework does not include such a method.

좋은 소식은 모든 명명 컨테이너를 재귀적으로 검색 하는 자체 FindControl 메서드를 만들 수 있다는 것입니다.The good news is that we can create our own FindControl method that recursively searches all naming containers. 실제로 확장 메서드 를 사용 하 여 Control 클래스에 FindControlRecursive 메서드를 표시 하 여 기존 FindControl 메서드와 함께 사용할 수 있습니다.In fact, using extension methods we can tack on a FindControlRecursive method to the Control class to accompany its existing FindControl method.

Note

확장 메서드는 C# 3.0 및 Visual Basic 9의 새로운 기능으로, .NET Framework 버전 3.5 및 Visual Studio 2008와 함께 제공 되는 언어입니다.Extension methods are a feature new to C# 3.0 and Visual Basic 9, which are the languages that ship with the .NET Framework version 3.5 and Visual Studio 2008. 즉, 확장 메서드를 사용 하면 개발자가 특수 구문을 통해 기존 클래스 형식에 대 한 새 메서드를 만들 수 있습니다.In short, extension methods allow for a developer to create a new method for an existing class type through a special syntax. 이 유용한 기능에 대 한 자세한 내용은 my 문서를 참조 하세요. 확장 메서드를 사용 하 여 기본 형식 기능 확장을 참조 하세요.For more information on this helpful feature, refer to my article, Extending Base Type Functionality with Extension Methods.

확장 메서드를 만들려면 PageExtensionMethods.vb이라는 App_Code 폴더에 새 파일을 추가 합니다.To create the extension method, add a new file to the App_Code folder named PageExtensionMethods.vb. controlID이라는 String 매개 변수를 입력으로 사용 하는 FindControlRecursive 라는 확장명 메서드를 추가 합니다.Add an extension method named FindControlRecursive that takes as an input a String parameter named controlID. 확장 메서드가 제대로 작동 하려면 클래스가 Module로 표시 되 고 확장 메서드에 <Extension()> 특성이 접두사로 추가 되는 것이 중요 합니다.For extension methods to work properly, it is vital that the class be marked as a Module and that the extension methods be prefixed with the <Extension()> attribute. 또한 모든 확장 메서드는 확장 메서드가 적용 되는 형식의 개체를 첫 번째 매개 변수로 허용 해야 합니다.Moreover, all extension methods must accept as their first parameter an object of the type to which the extension method applies.

PageExtensionMethods.vb 파일에 다음 코드를 추가 하 여이 ModuleFindControlRecursive 확장 메서드를 정의 합니다.Add the following code to the PageExtensionMethods.vb file to define this Module and the FindControlRecursive extension method:

Imports System.Runtime.CompilerServices

Public Module PageExtensionMethods
 <Extension()> _
  Public Function FindControlRecursive(ByVal ctrl As Control, ByVal controlID As String) As Control
 If String.Compare(ctrl.ID, controlID, True) = 0 Then
 ' We found the control!
 Return ctrl
 Else
 ' Recurse through ctrl's Controls collections
 For Each child As Control In ctrl.Controls
 Dim lookFor As Control = FindControlRecursive(child, controlID)

 If lookFor IsNot Nothing Then
 Return lookFor  ' We found the control
 End If
 Next

 ' If we reach here, control was not found
 Return Nothing
 End If
 End Function
End Module

이 코드를 사용 하면 IDIssues.aspx 페이지의 코드를 사용 하는 클래스를 반환 하 고 현재 FindControl 메서드 호출을 주석 처리 합니다.With this code in place, return to the IDIssues.aspx page's code-behind class and comment out the current FindControl method calls. Page.FindControlRecursive("controlID")에 대 한 호출로 대체 합니다.Replace them with calls to Page.FindControlRecursive("controlID"). 확장 메서드에 대 한 자세한 내용은 IntelliSense 드롭다운 목록 내에 직접 표시 된다는 것입니다.What's neat about extension methods is that they appear directly within the IntelliSense drop-down lists. 그림 7에 표시 된 것 처럼 Page를 입력 하 고 period를 누르면 FindControlRecursive 메서드가 다른 Control 클래스 메서드와 함께 IntelliSense 드롭다운에 포함 됩니다.As Figure 7 shows, when you type Page and then hit period, the FindControlRecursive method is included in the IntelliSense drop-down along with the other Control class methods.

확장 메서드는 IntelliSense 드롭다운에 포함 되어 있습니다.Extension Methods are Included in the IntelliSense Drop-Downs

그림 07: 확장 메서드가 IntelliSense 드롭다운에 포함 되어 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 07: Extension Methods are Included in the IntelliSense Drop-Downs (Click to view full-size image)

SubmitButton_Click 이벤트 처리기에 다음 코드를 입력 하 고 페이지를 방문 하 여 나이를 입력 하 고 "제출" 단추를 클릭 하 여 테스트 합니다.Enter the following code into the SubmitButton_Click event handler and then test it by visiting the page, entering your age, and clicking the "Submit" button. 그림 6에 표시 된 것 처럼 결과로 생성 되는 출력은 "사용 기간 이전!"의 메시지입니다.As shown back in Figure 6, the resulting output will be the message, "You are age years old!"

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim ResultsLabel As Label = CType(Page.FindControlRecursive("Results"), Label)
 Dim AgeTextBox As TextBox = CType(Page.FindControlRecursive("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

Note

확장 메서드는 3.0 및 Visual Basic C# 9에 처음으로 사용 되므로 Visual Studio 2005를 사용 하는 경우 확장 메서드를 사용할 수 없습니다.Because extension methods are new to C# 3.0 and Visual Basic 9, if you are using Visual Studio 2005 you cannot use extension methods. 대신 도우미 클래스에서 FindControlRecursive 메서드를 구현 해야 합니다.Instead, you'll need to implement the FindControlRecursive method in a helper class. Rick Strahl 에는 ASP.NET 메이저 Pages 및 FindControl의 블로그 게시물에 이러한 예가 있습니다.Rick Strahl has such an example in his blog post, ASP.NET Maser Pages and FindControl.

4 단계: 클라이언트 쪽 스크립트에서 올바른id특성 값 사용Step 4: Using the CorrectidAttribute Value in Client-Side Script

이 자습서의 소개에서 설명한 것 처럼 웹 컨트롤의 렌더링 된 id 특성은 클라이언트 쪽 스크립트에서 특정 HTML 요소를 프로그래밍 방식으로 참조 하는 데 사용 되는 경우가 많습니다.As noted in this tutorial's introduction, a Web control's rendered id attribute is oftentimes used in client-side script to programmatically reference a particular HTML element. 예를 들어, 다음 JavaScript는 id 따라 HTML 요소를 참조 하 고 모달 메시지 상자에 해당 값을 표시 합니다.For example, the following JavaScript references an HTML element by its id and then displays its value in a modal message box:

var elem = document.getElementById("Age");
if (elem != null)
    alert("You entered " + elem.value + " into the Age text box.");

명명 컨테이너를 포함 하지 않는 ASP.NET 페이지에서 렌더링 된 HTML 요소의 id 특성은 웹 컨트롤의 ID 속성 값과 동일 합니다.Recall that in ASP.NET pages that do not include a naming container, the rendered HTML element's id attribute is identical to the Web control's ID property value. 이로 인해 JavaScript 코드에 id 특성 값을 하드 코드 하는 것이 좋습니다.Because of this, it is tempting to hard code in id attribute values into JavaScript code. 즉, 클라이언트 쪽 스크립트를 통해 Age TextBox 웹 컨트롤에 액세스 하려면 document.getElementById("Age")에 대 한 호출을 통해이 작업을 수행 합니다.That is, if you know you want to access the Age TextBox Web control through client-side script, do so via a call to document.getElementById("Age").

이 방법의 문제는 마스터 페이지 또는 기타 명명 컨테이너 컨트롤을 사용할 때 렌더링 된 HTML id 웹 컨트롤의 ID 속성과 동의어가 없다는 것입니다.The problem with this approach is that when using master pages (or other naming container controls), the rendered HTML id is not synonymous with the Web control's ID property. 첫 번째는 브라우저를 통해 페이지를 방문 하 고 소스를 확인 하 여 실제 id 특성을 확인 하는 것입니다.Your first inclination may be to visit the page through a browser and view the source to determine the actual id attribute. 렌더링 된 id 값을 알고 있으면 getElementById 호출에 붙여넣어 클라이언트 쪽 스크립트를 통해 작업 해야 하는 HTML 요소에 액세스할 수 있습니다.Once you know the rendered id value, you can paste it into the call to getElementById to access the HTML element you need to work with through client-side script. 이 방법은 페이지의 컨트롤 계층 구조를 변경 하거나 명명 컨트롤의 ID 속성을 변경 하 여 결과 id 특성을 변경 하므로 JavaScript 코드가 손상 되기 때문에 이상적이 지 않습니다.This approach is less than ideal because certain changes to the page's control hierarchy or changes to the ID properties of the naming controls will alter the resulting id attribute, thereby breaking your JavaScript code.

웹 컨트롤의 ClientID 속성을 통해 서버 쪽 코드에서 렌더링 되는 id 특성 값에 액세스할 수 있다는 것이 좋습니다.The good news is that the id attribute value that is rendered is accessible in server-side code through the Web control's ClientID property. 이 속성을 사용 하 여 클라이언트 쪽 스크립트에서 사용 되는 id 특성 값을 확인 해야 합니다.You should use this property to determine the id attribute value used in client-side script. 예를 들어 JavaScript 함수를 페이지에 추가 하려면 호출 되는 경우 모달 메시지 상자에 Age 텍스트 상자 값을 표시 하 고 Page_Load 이벤트 처리기에 다음 코드를 추가 합니다.For example, to add a JavaScript function to the page that, when called, displays the value of the Age TextBox in a modal message box, add the following code to the Page_Load event handler:

ClientScript.RegisterClientScriptBlock(Me.GetType(), "ShowAgeTextBoxScript", _
 "function ShowAge() " & vbCrLf & _
 "{" & vbCrLf & _
 " var elem = document.getElementById('" & AgeTextBox.ClientID & "');" & vbCrLf & _
 " if (elem != null)" & vbCrLf & _
 " alert('You entered ' + elem.value + ' into the Age text box.');" & vbCrLf & _
 "}", True)

위의 코드는 getElementById에 대 한 JavaScript 호출에 Age TextBox의 ClientID 속성 값을 삽입 합니다.The above code injects the value of the Age TextBox's ClientID property into the JavaScript call to getElementById. 브라우저를 통해이 페이지를 방문 하 고 HTML 소스를 보면 다음 JavaScript 코드를 찾을 수 있습니다.If you visit this page through a browser and view the HTML source, you'll find the following JavaScript code:

<script type="text/javascript">
//<![CDATA[
function ShowAge()
{
 var elem = document.getElementById('ctl00_MainContent_Age');
 if (elem != null)
 alert('You entered ' + elem.value + ' into the Age text box.');
}//]]>
</script>

getElementById에 대 한 호출 내에 올바른 id 특성 값 ctl00_MainContent_Age표시 되는 방법을 확인 합니다.Notice how the correct id attribute value, ctl00_MainContent_Age, appears within the call to getElementById. 이 값은 런타임에 계산 되기 때문에 페이지 컨트롤 계층 구조에 대 한 이후 변경 내용에 관계 없이 작동 합니다.Because this value is calculated at runtime, it works regardless of later changes to the page control hierarchy.

Note

이 JavaScript 예제에서는 서버 컨트롤에서 렌더링 한 HTML 요소를 올바르게 참조 하는 JavaScript 함수를 추가 하는 방법만 보여 줍니다.This JavaScript example merely shows how to add a JavaScript function that correctly references the HTML element rendered by a server control. 이 함수를 사용 하려면 문서가 로드 될 때 또는 특정 사용자 작업이 transpires 때 함수를 호출 하기 위해 추가 JavaScript를 작성 해야 합니다.To use this function you would need to author additional JavaScript to call the function when the document loads or when some specific user action transpires. 이러한 항목 및 관련 항목에 대 한 자세한 내용은 클라이언트 쪽 스크립트 작업을 참조 하세요.For more information on these and related topics, read Working with Client-Side Script.

요약Summary

특정 ASP.NET 서버 컨트롤은 FindControl 메서드에서 canvassed 컨트롤의 범위 뿐만 아니라 해당 하위 컨트롤의 렌더링 된 id 특성 값에 영향을 주는 명명 컨테이너 역할을 합니다.Certain ASP.NET server controls act as naming containers, which affects the rendered id attribute values of their descendent controls as well as the scope of controls canvassed by the FindControl method. 마스터 페이지와 관련 하 여 마스터 페이지와 해당 ContentPlaceHolder 컨트롤은 모두 명명 컨테이너입니다.With regards to master pages, both the master page itself and its ContentPlaceHolder controls are naming containers. 따라서 FindControl를 사용 하 여 콘텐츠 페이지 내에서 프로그래밍 방식으로 컨트롤을 참조 하려면 약간 더 많은 작업을 수행 해야 합니다.Consequently, we need to put forth a bit more work to programmatically reference controls within the content page using FindControl. 이 자습서에서는 ContentPlaceHolder 컨트롤로 드릴 하 고 해당 FindControl 메서드를 호출 하는 두 가지 방법을 살펴보았습니다. 그리고 모든 명명 컨테이너를 재귀적으로 검색 하는 자체 FindControl 구현을 롤백합니다.In this tutorial we examined two techniques: drilling into the ContentPlaceHolder control and calling its FindControl method; and rolling our own FindControl implementation that recursively searches through all naming containers.

서버 쪽 문제를 명명 하는 컨테이너는 웹 컨트롤을 참조 하는 것과 관련해 서 소개 합니다. 또한 클라이언트 쪽 문제도 있습니다.In addition to the server-side issues naming containers introduce with regards to referencing Web controls, there are also client-side issues. 명명 컨테이너가 없을 경우 웹 컨트롤의 ID 속성 값과 렌더링 된 id 특성 값은 동일 합니다.In the absence of naming containers, the Web control's ID property value and rendered id attribute value are one in the same. 그러나 명명 컨테이너가 추가 되어 렌더링 된 id 특성에는 웹 컨트롤의 ID 값과 해당 컨트롤 계층의 상위 구조에 있는 명명 컨테이너가 모두 포함 됩니다.But with the addition of naming container, the rendered id attribute includes both the ID values of the Web control and the naming container(s) in its control hierarchy's ancestry. 이러한 명명 문제는 웹 컨트롤의 ClientID 속성을 사용 하 여 클라이언트 쪽 스크립트에서 렌더링 된 id 특성 값을 확인 하는 동안 문제가 되지 않습니다.These naming concerns are a non-issue as long as you use the Web control's ClientID property to determine the rendered id attribute value in your client-side script.

행복 한 프로그래밍Happy Programming!

추가 참고 자료Further Reading

이 자습서에서 설명 하는 항목에 대 한 자세한 내용은 다음 리소스를 참조 하세요.For more information on the topics discussed in this tutorial, refer to the following resources:

저자 정보About the Author

Scott Mitchell는 여러 ASP/ASP. NET books의 작성자와 4GuysFromRolla.com의 창립자가 1998부터 Microsoft 웹 기술을 사용 하 여 작업 했습니다.Scott Mitchell, author of multiple 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 3.5을 sams teach yourself것입니다.His latest book is Sams Teach Yourself ASP.NET 3.5 in 24 Hours. Scott은 mitchell@4GuysFromRolla.com 또는 http://ScottOnWriting.NET의 블로그를 통해 연결할 수 있습니다.Scott can be reached at mitchell@4GuysFromRolla.com or via his blog at http://ScottOnWriting.NET.

특별히 감사 합니다.Special Thanks To

이 자습서 시리즈는 많은 유용한 검토자가 검토 했습니다.This tutorial series was reviewed by many helpful reviewers. 이 자습서에 대 한 잠재 고객 검토자는 Zack Jones와 Suchi 바의 Jee 였습니다.Lead reviewers for this tutorial were Zack Jones and Suchi Barnerjee. 예정 된 MSDN 문서를 검토 하는 데 관심이 있나요?Interested in reviewing my upcoming MSDN articles? 그렇다면 mitchell@4GuysFromRolla.com에서 줄을 삭제 합니다.If so, drop me a line at mitchell@4GuysFromRolla.com.