Question

J'ai TemplateField dynamiquement ajouté à un GridView personnalisé.

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

En réponse à une grille de commande (insertion / mise à jour / supprimer), une méthode appelée GetRowControls qui est appelé itère à travers les colonnes de la GridRow particulier, et ajoute chacun de ses commandes à un dictionnaire.

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

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

...

Alors que cela fonctionne très bien pour les deux champs du modèle et des contrôles liés ajoutés déclarative, ainsi que des champs de modèle non-dynamique ajouté programatically.

Toutefois, lorsque le contrôle est un contrôle TemplateField ajouté dynamiquement ctrl.ID est toujours nul et donc la déclaration ci-dessus jette une exception.

Je l'ai regardé dans ce avec réflecteur parce que je trouve que lorsque je la variable examiné dans la fenêtre immédiate dans VS 2005 à savoir? Ctrl, ctrl.ID énumérerais une valeur. Je l'ai depuis établi que cela est parce que, dans la liste? Ctrl dans la fenêtre immédiate, la proprty ClientID est appelé et appelle ClientID EnsureID (), ce qui définit 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;
    }
}

Je suppose donc que ClientID, UniqueId et ID sont nuls - bien que ci-dessus en train de lire les deux premiers déclenchera tous être configurés. A noter également que NamingContainer n'est pas nul. Il a été défini.

Ainsi, le travail autour de cela est assez simple à savoir vérifier ctrl.ID == null et si oui, il suffit de lire ctrl.ClientID. Et c'est ce que je l'ai fait parce que le temps sage, je dois vraiment obtenir un tortiller sur. Mais je suis toujours intéressé par la réponse si quelqu'un le sait du haut de leurs têtes.

Pourquoi la valeur d'identité d'un contrôle enfant, d'un TemplateField, fixé à un moment différent de celui d'autres contrôles dynamiquement ajouté?

Était-ce utile?

La solution

Il est pas qu'ils se comportent différemment, mais presque toujours lorsque vous ajoutez un contrôle que vous définissez l'ID déclarative tout de suite. Essayez d'ajouter une étiquette sans ID à une page et parcourez la collection de commande et vérifier son identité, il sera nul (assurez-vous de ne pas montrer son clientID car il obtiendrait l'ID remplie):

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

Notez également que si vous l'exécutez comme vous obtenez une durée sans ID.

Autres conseils

Freddy est correct.

Vous êtes responsable de la mise ID dans la méthode InstantiateIn. Et il est logique que les clientId génère automatiquement si non spécifié autrement.

Les contrôles déclaratifs obtiennent leurs ID attribués par un constructeur de la page lors de la compilation d'une page. Si vous deviez regarder l'un des fichiers de temporaires générés dans le dossier « Temporary ASP.NET Files », vous pouvez trouver quelque chose comme ça (pragma dépouillé):

//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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top