Quando um controle em um TemplateField programaticamente adicionado tem seu conjunto de propriedades ID?

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

Pergunta

Eu tenho um TemplateField que é adicionado dinamicamente a um GridView personalizado.

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;
        }
    }

Em resposta a uma grade Command (insert / update / delete), um método chamado GetRowControls é chamado, que percorre o colunas na gridrow particular, e adiciona cada um dos seus controles a um dicionário.

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

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

...

Assim, esta multa obras tanto para campo de modelo e controles acoplados adicionados declarativamente, bem como campos do modelo dinâmico-non adicionado programaticamente.

No entanto, quando o controle é um controle TemplateField adicionado dinamicamente ctrl.ID é sempre nula e, portanto, a afirmação acima lança uma exceção.

Eu olhei para isso com refletor porque descobri que quando examinei a variável na janela imediata no VS 2005 ou seja? Ctrl, lista ctrl.ID que um valor. Eu já estabelecido que isso é porque na listagem? Ctrl na janela imediata, o ClientID proprty é chamado e ClientID chama EnsureID (), que por sua vez, define 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;
    }
}

Então, eu estou supondo que ClientID, UniqueId e ID são todos nulos - embora como acima apenas ler as duas primeiras irá desencadear tudo para ser definido. Observe também que NamingContainer não é nulo. Tem sido set.

Assim, a solução para este é bastante simples ou seja, verificar se há ctrl.ID == null e se assim for simplesmente ler ctrl.ClientID. E isso é o que eu fiz, porque o tempo sábio eu realmente tenho para obter uma contorcer diante. Mas eu ainda estou interessado na resposta se alguém conhece-lo fora do topo de suas cabeças.

Por que o valor ID de um controle filho, de um TemplateField adicionado dinamicamente, fixado em um momento diferente da de outros controles?

Foi útil?

Solução

Não é que eles se comportam de maneira diferente, mas que quase sempre quando você adiciona um controle declarativamente definir o ID de imediato. Tente adicionar uma etiqueta com nenhuma identificação para uma página e navegar pela coleção de controle e verificar o seu ID, será nula (certifique-se de não mostrar a sua clientID uma vez que se o ID preenchido):

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

Além disso, observe que, se você executá-lo assim que você começa um período sem ID.

Outras dicas

Freddy está correto.

Seu são responsáveis ??por definir IDs dentro do método InstantiateIn. E faz sentido que ClientID auto-gera-los se não especificado de outra forma.

Os controles declarativos se seus IDs atribuído por um construtor de página durante a compilação de uma página. Se você estava a olhar para um dos arquivos cs temporários gerados na pasta "Arquivos temporários ASP.NET", você encontraria algo assim (pragmas despojado):

//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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top