Setting Client IDs

  ASP.NET 4.0의 새로 생긴 ClientIDMode 속성은, ASP.NET에서 컨트롤 ID의 네이미을 결정합니다. 랜더링된 HTML 요소의 ID속성을 자바스크립트에서 랜더링된 HTML을 ID 로 참조하기 위해 꼭 필요합니다.
  기존의 서버 컨트롤은 ClientID 속성을 통해 HTML 요소이 id를 생성하였습니다. 기존의 알고리즘은 컨테이너 기반으로 순차적으로 HTML 요소의 id를 생성하였고, 데이터그리드 같은 컨트롤은 기존ClientID+순번을 추가하여 랜더링 하였습니다. 그래야 HTML 페이지에서 ID 가 유일하다는 보장을 할 수 있었죠. 이런 문제로 컨트롤ID는 매우 복잡해져서 클라이언트 스크립트에서 HTML요소로 접근하기 매우 까다로웠습니다.

  새로운 ClientIDMode 속성은 당신이  클라이언트 ID가 컨트롤을 위하여 어떻게 발생될지를 더 정확하게 지정 할수 있게합니다.당신은 어떤 컨트롤을 위하여 ClientIDMode  속성을 해당 페이지에서 설정이 가능합니다. 가능한 설정들은 다음과 같습니다:

  • AutoID — 이것은 ASP.NET 초기 버전에서와 같이 ClientID  속성 값을 발생하는 알로리즘과 같습니다.
  • Static — 이것은 ClientID 값이 ID와 같게 지정합니다. 단 상위에서 지명하는 컨테이너들 중에 ID들을 연관짓는 것이 없을 경우입니다.
  • Predictable — 이 옵션은 본래 반복적인 템플릿을 사용하는 데이터 컨트롤 안에서의 사용을 위한 것입니다. 그것은 컨트롤의 이름있는 컨테이너의 ID 속성과 연관을 맺습니다. 그러나  ClientID 값은 "ctlxxx"와 같은 문자열은 포함하지 않습니다. 이 설정은 컨트롤의 ClientIDRowSuffix 속성과 연계하여 동작합니다.  당신은 데이터 필드의 이름으로 ClientIDRowSuffix  속성을 설정합니다. 그리고 그 필드의 값은 발생된 ClientID  위한 접미사로 사용됩니다.
  • Inherit — 이 설정은 컨트롤들을 위한 기본 속성입니다. 그리고 그것은 컨트롤ID 발생이 상위의 것과 같게 지정합니다.

  ASP.NET 4.0에서는 Page 지시자를 통해 ClientIDMode 속성을 설정할 수 있습니다. 이 속성을 통해 페이지의 모든 컨트롤의 랜더링 방식의 기본값을 설정할 수 있습니다.

  Page의 ClientIDModel의 기본값은 AutoID이며, 컨트롤 측면에서는 ClientIDMode 의 기본값은 Inherit입니다. 그래서 이 속성을 굳이 설정하지 않으면 AutoID 가 기본값이 됩니다.

 @ Page 지시문 안에서 페이지 레벨상의 값을 설정 할 수 있습니다. 다음의 예를 보세요:

<%@ Page Language="C#" AutoEventWireup="true"
  CodeFile="Default.aspx.cs"
  Inherits="_Default"
  ClientIDMode="Predictable" %>

당신은 또한 머신 레빌 혹은 어플리케이션 레벨의 구성 파일안에서 ClientIDMode 값을 설정 할 수 있습니다. 이것은 어플리케이션 상에서 모든 페이지의 코든 컨트롤들의 ClientIDMode 의 기본값을 설정을 정의합니다. 당신의 머신 레빌에서 값을 설정한다면, 그것은 그 컴퓨터의 모든 웹사이트의 ClientIDMode 값을 기본 설정합니다. 다음의 예는 구성 파일에서 ClientIDMode 를 설정하는 것을 보여드립니다:

<system.web>
  <pages clientIDMode="Predictable"></pages>
</system.web>

앞에 예제를 보면, ClientID 속성의 값은 컨트롤 상위의 네이밍 컨테이너로 부터 상속을 받습니다.어떤 시나리오에서
당신이 마스터 페이지를 사용하고 있는 상황이라면, 컨트롤들은 다음의 렌더링된 HTML 안의 그것들 처럼 ID와 함께 끝날
것입니다:

 

<div id="ctl00_ContentPlaceHolder1_ParentPanel">
<div id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1">
<input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1" type="text" value="Hello!"       id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1" />
</div>
</div>

비록 마크업 안에서 보여진 (TextBox 컨트롤로 부터) input 요소가 (내포된 ContentPlaceholder  컨트롤들)페이지 깊숙한 곳에
단지 두 개의 네이밍 컨트롤이 있더라도, 마스터 페이지가 처리되는 방식 때문에, 마지막 결과물은 다음과 같은 컨트롤
아이디입니다.


ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1
 
이것은 긴 아이디입니다. 그것은 페이지 안에서 유니크한 것을 보장합니다. 그러나 대부분의 목적에는 불필요하게 깁니다.
생각해보라 당신이 랜더링된 아이디의 길이를 줄이기 원하고, 아이디가 어떻게 발생하는지를 더 말하기 원한다면...(예를들어, 당신은 앞에 붙은 'ctlxxx' 제거하기 원합니다.) 이것을 해결하는 가장 쉬운 방법은 다음의 예처럼 ClientIDMode 속성을 설정하는 것입니다:
<tc:NamingPanel runat="server" ID="ParentPanel" ClientIDMode="Static">  
<tc:NamingPanel runat="server" ID="NamingPanel1" ClientIDMode="Predictable">    
<asp:TextBox ID="TextBox1" runat="server" Text="Hello!"></asp:TextBox>  
</tc:NamingPanel>
</tc:NamingPanel>

   
   이 샘플에서 ClientIDMode 속성은 가장 바깥쪽에 있는 NamingPanel  요소를 위하여 Static 으로 설정하였습니다. 그리고 내부의 NamingControl  요소를 위하여 Predictable 으로 설정하였습니다. 이 설정은 다음의 마크업 같은 결과를 만듭니다.(나머지 페이지와 마스터 페이지는 이전의 예처럼 같게 되는 것을 취하게 됩니다. )

<div id="ParentPanel">
  <div id="ParentPanel_NamingPanel1">
    <input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1"
      type="text" value="Hello!" id="ParentPanel_NamingPanel1_TextBox1" />
  </div>

 
   Static
설정은 가장 바깥 쪽의 NamingPanel 요소 안의 어떤 컨트롤들을 위한 네이밍 계층을 리셋하는 효과를 같고, 발생된 아이디로 부터 ContentPlaceHolderMasterPage 아이디의 제거를 합니다. (랜더링된 요소의 name 속성은 영향받지 않는다. 그 결과 정상적은 ASP.NET 기능은 이벤트, 뷰 스테이드 등을 유지하게 됨을 기억해라. ) 네이밍 계층을 리셋하는 멋진 부수 효과는 당신이 만약 다른 ContentPlaceholder 컨트롤로 NamingPanel  요소를 마크업을 이동하더라도, 랜더링된 클라이언트 아이디는 같게 남습니다.

   Note:  랜더링된 컨트롤 아이디들이 유니크한 것을 확실히 하는 것은 당신에게 달려 있습니다. 그것들이 유니크 하지 않다면, 그것은 개별적인 HTML 요소들을 위한 유니크 아이디들을 요구하는 기능이 깨질 수 있습니다. 예를들면 클라이언트의 document.getElementById  함수같은 것입니다.

 

Creating Predictable Client IDs in Data-Bound Controls

    레거시 알고리즘에 의한 데이터 바운드 리스트 컨트롤안의 컨트롤들이 발생 될 때의 ClientID 값은 길고 전혀 예상하지 못하게 될 수 있습니다. ClientIDMode 기능은 이 아이디들이 어떻게 발생되는지를 넘어서 당신이 더 많은 컨트롤을 같는데 도움을 줍니다.  ListView 컨트롤을 포함한 다음의 마크업을 보세요:

<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource1"
    OnSelectedIndexChanged="ListView1_SelectedIndexChanged"
    ClientIDMode="Predictable"
    RowClientIDRowSuffix="ProductID">
</asp:ListView>


이전의 예에서 ClientIDModeRowClientIDRowSuffix 속성은 마크업 안에 설정이 됩니다. ClientIDRowSuffix 속성은 단지 데이터 바운드 컨트롤들 안에서 사용될 수 있습니다. 그리고 그것의 수행은 당신이 사용하는 컨트롤에 의존적이지 않게 합니다. 차이점은 이것들입니다:

  • GridView control —  당신은 데이터 소스 안에 하나 혹은 더 많은 컬럼들의 이름을 명기 할 수 있습니다.그리고 그것들은 클라이언트 아이디들을 창조하는 실행 시간에 조합이 됩니다. 예를들어 당신이 RowClientIDRowSuffix 를  "ProductName, ProductId"로 설정한다면, 랜더링된 요소들을 위한 클라이언트 아이디들은 다음과 같은 형식을 가질 것입니다:
 rootPanel_GridView1_ProductNameLabel_Chai_1
  • ListView control — 당신은 클라이언트 아이디에 덧붙여진 데이터 소스안의 한 컬럼을 명시 할 수 있습니다. 예를 들어, 당신이 ClientIDRowSuffix 속성을 "ProductName"으로 설정한다면, 랜더링된 컨트롤들의 아이디들은 다음과 같은 형식을 가질 것입니다:
 rootPanel_ListView1_ProductNameLabel_1


이 경우에, 1의 흔적은 현재 데이터 아이템의 product ID로 부터 상속을 받습니다.

  • Repeater control —  이 컨트롤은 ClientIDRowSuffix 속성을 지원하지 않습니다.  Repeater 컨트롤에서 현재 행의 인덱스가 사용되었습니다. 당신이  Repeater  컨트롤에서  ClientIDMode="Predictable" 를 사용 했을 때, 클라이언트 아이디들은 다음의 형식으로 발생 될 것입니다:
Repeater1_ProductNameLabel_0


0의 흔적은 현재 행의 인덱스 입니다. FormViewDetailsView 컨트롤들은 다중 행을 보여주지 않습니다. 그래서 그것들은 ClientIDRowSuffix 지원하지 않습니다.

Persisting Row Selection in Data Controls


   GridView
ListView 컨트롤들은 사람들에게 행을 선택하게 할 수 있습니다. 이전의 ASP.NET 버전에서, 선택은 페이지 상의 행 인덱스에 기반하였습니다.  예를 들어, 당신이 페이지 1의 세번째 아이템을 선택하고, 페이지 2로 넘어가면, 두번째 페이지의 세번째 아이템이 선택됩니다.  지속된 선택은 .NET Framework 3.5 SP1의 동적 데이터 프로젝트안에서만 초기에 지원이 되었던 새로운 특성입니다. 이 특성을 활성화 했을 때, 현재 선택된 아이템은 그것들을 위한 데이터키에 기반합니다. 이것이 의미하는 것은 당산이 1 페이지의 세번째 행을 클릭한 다음 2 페이지로 이동하더라도 2 페이지에는 어떤 것도 선택된 것이 없습니다. 당신이 1 페이지로 돌아 갔을 때, 세번째 행이 여전히 선택되어 집니다.

   이 것은 초기 ASP.NET 버전에서의 수행 보다 훨신 더 자연스러운 선택 방법입니다. 지속된 선택은 지금 EnablePersistedSelection 속성을 사용하는 모든 프로젝트 상의 GridViewListView 에 지원이 됩니다. 다음의 예를 보세요.

<asp:GridView id="GridView2" runat="server" EnablePersistedSelection="true">
</asp:GridView>