2009-04-01 2 views
1

사용자 정의 GridView에 동적으로 추가되는 TemplateField가 있습니다. 그리드 커맨드에 응답프로그래밍 방식으로 추가 된 TemplateField의 컨트롤에 'ID 속성이 설정되어 있습니까?

void ITemplate.InstantiateIn(System.Web.UI.Control container) 
    { 
     switch (_templateType) 
     { 
      case ListItemType.Header: 
       if (this.ParentGridView.ShowDeleteHeaderImage) 
       { 
        Image hImg = new Image(); 
        hImg.ImageUrl = this.ParentGridView.DeleteHeaderImageUrl; 
        hImg.AlternateText = "Mark for Deletion"; 
        container.Controls.Add(hImg); 
       } 
       else 
       { 
        Label l = new Label(); 
        l.Text = "Del"; 
        container.Controls.Add(l); 
       } 
       break; 
      case ListItemType.Item: 
       container.Controls.Add(new CheckBox()); 
       break; 
      case ListItemType.EditItem: 
       break; 
      case ListItemType.Footer: 
       QLImageButton deleteButton = new QLImageButton(); 
       deleteButton.Settings.ImageId = "cmdQLGVDelete"; 
       deleteButton.Settings.ImageUrl = this.ParentGridView.DeleteImageUrl; 
       deleteButton.CommandName = "Delete"; 
       container.Controls.Add(deleteButton); 
       break; 
     } 
    } 

은 (삽입/갱신/삭제) 방법이라고 GetRowControls라는 특정 gridrow의 열 관통하는 반복하고, 사전에 그 제어를 각각 추가된다.

Dictionary<string, WebControl> GetRowControls(GridViewRow row) 
... 

rowControls.Add(ctrl.ID, (WebControl)ctrl); 

... 

이렇게하면 템플릿 필드와 바인딩 된 컨트롤이 선언적으로 추가되고 동적으로 추가되는 템플릿 필드가 프로그래밍 방식으로 추가되어 잘 작동합니다.

그러나 컨트롤이 동적으로 추가 된 TemplateField 컨트롤 인 경우 ctrl.ID는 항상 null이므로 위의 문은 예외를 throw합니다.

VS 2005 즉치 창에서 변수를 검사 할 때? ctrl, ctrl.ID가 값을 나열해야한다는 것을 알았 기 때문에 Reflector를 조사했습니다. 그 이후로 바로 창에 목록? ctrl, proprty ClientID가 호출되고 ClientID가 EnsureId()를 호출하여 차례대로 ID를 설정하기 때문입니다.

public virtual string ClientID 
{ 
    get 
    { 
     this.EnsureID(); 
     string uniqueID = this.UniqueID; 
     if ((uniqueID != null) && (uniqueID.IndexOf(this.IdSeparator) >= 0)) 
     { 
      return uniqueID.Replace(this.IdSeparator, '_'); 
     } 
     return uniqueID; 
    } 
} 

그래서 내가 된 ClientID, UNIQUEID 및 ID가 모두 null이 있으리라 믿고있어 - 위와 같이 단지 처음 두 모든 설정을 트리거 읽고 있지만. NamingContainer가 null이 아니기 때문에주의 해주세요. 그것은 설정되었습니다.

그래서이 문제는 매우 간단합니다. 즉, ctrl.ID == null을 확인하고 ctrl.ClientID를 읽으면됩니다. 그리고 시간이 현명하기 때문에 내가 한 일이 바로 내가 정말로 망설임을 겪어야한다는 것입니다. 그러나 누군가가 머리 꼭대기에서 그것을 안다면 나는 아직도 대답에 흥미가있다.

동적으로 추가 된 TemplateField의 자식 컨트롤의 ID 값이 다른 컨트롤의 시간과 다른 이유는 무엇입니까?

+0

그래서 완전히 옮겼습니다. 스틱의 잘못된 끝으로 멀리 떨어져서 가장 확실한 답을 모두 놓쳤습니다. 수락 된 답변을 참조하십시오. – rism

+0

좋은 질문이라고 생각했습니다. 거의 20 년 동안의 프로그래밍 과정에서 문제를 해결하는 데 가장 쉬운 문제가 가장 자주 발생하는 것으로 나타났습니다. – Ruslan

+0

@Ruslan - 잘 해줘서 고마워하지만 여전히 바보 같은 느낌. 대답이 실질적으로 질문에 나오는 시대입니다.;) 좋은 소식은 반사경을 가지고 주위를 두드리는 동안 두 가지 더 많은 것을 배웠기 때문에 전체 손실이 아닙니다. – rism

답변

2

그들은 다르게 동작하지 않지만, 거의 항상 컨트롤을 선언적으로 추가하면 ID를 바로 설정합니다. (이 ID가 채워지는 것이기 때문에 그것의 클라이언트 ID를 표시하지 않도록주의)이 null이됩니다, 페이지에없는 ID로 레이블을 추가 시도하고 제어 컬렉션을 탐색하고 ID를 확인 :

<asp:Label runat="server">something</asp:Label> 

는 또한

주의 만약 당신이 그것을 실행하면 당신은 ID가없는 범위를 얻게됩니다.

+0

대답은 너무 blindingly 분명 나는 어리석은 4 1 질문에 질문을 느낀다. 어떻게하면 container.Controls.Add (새로운 CheckBox()); 나의 방어에서 나는 새로운 "건강 차기"때문에 월요일에 카페인을 마시는 것을 2 바보 같이 결심했다고 지적하고 싶다;) – rism

2

프레디가 정확합니다.

귀하는 InstantiateIn 방법 내에 ID를 설정해야합니다. ClientID가 지정되지 않으면 자동으로 생성됩니다.

선언 컨트롤은 페이지를 컴파일하는 동안 페이지 작성자가 할당 한 ID를 가져옵니다. "Temporary ASP.NET Files 폴더"에서 생성 된 temp .cs 파일 중 하나를 보면 다음과 같은 것을 발견 할 수 있습니다 (pragma stripped) :

//creating a template field, where CopiledBindableTemplateBuilder is the ITemplate 
//and its InstantiateIn = @__BuildControl__control9 
@__ctrl.ItemTemplate = new System.Web.UI.CompiledBindableTemplateBuilder(
    new System.Web.UI.BuildTemplateMethod([email protected]__BuildControl__control9), 
    new System.Web.UI.ExtractTemplateValuesMethod([email protected]__ExtractValues__control9)); 

//and @__BuildControl__control9 calling @__BuildControlButton1 
private global::System.Web.UI.WebControls.Button @__BuildControlButton1() 
{ 
    global::System.Web.UI.WebControls.Button @__ctrl; 

    @__ctrl = new global::System.Web.UI.WebControls.Button(); 
    this.Button1 = @__ctrl; 
    @__ctrl.ApplyStyleSheetSkin(this); 
    @__ctrl.ID = "Button1"; //<-- here it gets an ID 
    @__ctrl.Text = "Button"; 
    return @__ctrl; 
} 
관련 문제