프로그래밍 방식으로 추가 된 템플릿 필드의 컨트롤에는 'ID 속성 세트가있는시기는 언제입니까?

StackOverflow https://stackoverflow.com/questions/703987

문제

사용자 정의 그리드 뷰에 동적으로 추가되는 템플릿 필드가 있습니다.

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라는 메소드가 호출되어 특정 그리드의 열을 통해 반복되고 각 컨트롤을 사전에 추가합니다.

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

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

...

따라서 이것은 템플릿 필드 및 바운드 컨트롤과 선언적으로 추가 된 템플릿 컨트롤과 동적 템플릿 필드에 대해 잘 작동합니다.

그러나 컨트롤이 템플릿 필드 컨트롤이 추가 된 경우 동적으로 ctrl.id는 항상 null이므로 위의 진술은 예외가 발생합니다.

vs 2005의 즉각적인 창에서 변수를 검사 할 때 ctrl.id가 값을 나열 할 것이라는 것을 알았 기 때문에 반사판으로 이것을 살펴 보았습니다. 그 이후로 이것은 바로 바로 즉시 CTRL에서 proprty clientId가 호출되고 clientId calls restId ()가 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, SightiD 및 ID는 모두 NULL이라고 가정합니다. 비록 위의 첫 두 가지를 읽는 것처럼 모든 것이 설정되도록 트리거됩니다. 또한 NamingContainer는 NULL이 아닙니다. 설정되었습니다.

따라서이를위한 작업은 Ctrl.id == NULL에 대한 매우 간단한 IE 검사이며 Ctrl.ClientID를 읽으십시오. 그리고 그게 내가 현명했기 때문에 내가 한 일은 정말로 깜짝 놀랐기 때문에 그 일입니다. 그러나 누군가가 머리 꼭대기에서 그것을 알고 있다면 여전히 대답에 관심이 있습니다.

동적으로 추가 된 템플릿 필드의 자식 제어의 ID 값이 다른 컨트롤과는 다른 시간에 설정된 이유는 무엇입니까?

도움이 되었습니까?

해결책

그것들이 다르게 행동하는 것이 아니라 거의 항상 컨트롤을 선언 적으로 추가 할 때 ID를 즉시 설정합니다. 페이지에 ID가없는 레이블을 추가하고 컨트롤 컬렉션을 탐색하고 ID를 확인하십시오. NULL이됩니다 (ID가 채워지기 때문에 ClientID를 표시하지 마십시오) :

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

또한 실행하면 ID가없는 스팬을 얻습니다.

다른 팁

프레디가 맞습니다.

Instantiatein 메소드 내에서 ID를 설정할 책임이 있습니다. 그리고 ClientID는 달리 지정되지 않은 경우 자동 생성을 의미합니다.

선언적 컨트롤은 페이지를 편집하는 동안 페이지 빌더에 의해 ID를 할당합니다. "임시 ASP.NET 파일 폴더"에서 생성 된 Temp .CS 파일 중 하나를 보려면 다음과 같은 것을 찾을 수 있습니다 (Pragmas 스트리핑).

//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(this.@__BuildControl__control9),
    new System.Web.UI.ExtractTemplateValuesMethod(this.@__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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top