Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    Consultant freelance, n'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

La methode FindControl

La méthode FindControl permet de trouver un contrôle à partir de son ID. Sans que l'on s'en rende compte, on l'utilise de plus en plus souvent. En effet ASP.net Ajax l'utilise très souvent en interne, ainsi lorsque l'on définit un trigger sur un UpdatePanel ou lorsque l'on renseigne la propriété AssociatedUpdatePanelID d'un UpdateProgress voir encore la propriété TargetControlID d'un extender, alors ASP.net utilise la méthode FindControl.

<asp:Button ID="btn1" runat="server" Text="go" OnClick="btn1_Click" /> <asp:UpdatePanel ID="up1" runat="server" > <ContentTemplate> <%=DateTime.Now.ToLongTimeString()%> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btn1" /> </Triggers> </asp:UpdatePanel> <asp:updateprogress id="upg1" runat="server" AssociatedUpdatePanelID="up1"> <ProgressTemplate> En cours ... </ProgressTemplate> </asp:updateprogress>

Il est donc intéressant de savoir comment fonctionne cette méthode en détail. La description de la méthode FindControl dans msdn nous donne très peu d'information :

Searches the current naming container for a server control with the specified id parameter.

En utilisant Reflector on comprend mieux comment fonctionne cette méthode. Pour vous l'expliquer, voici une version simplifiée de son code :

protected virtual Control FindControl(string id) { // vérification que les contrôles enfants sont bien créer this.EnsureChildControls(); /// this.flags[0x80] est vrai seulement si l'instance en cours implémente INamingContainer /// ce bloc nous informe que la méthode FindControl appelle la méthode FindControl /// de son NamingContainer ou de lui même s'il implémente INamingContainer if (!this.flags[0x80]) { Control namingContainer = this.NamingContainer; if (namingContainer != null) { return namingContainer.FindControl(id, pathOffset); } return null; } // this._occasionalFields.NamedControls est un dictionnaire d'id/control qui contient // tous les contrôles du namingContainer en cours if (this.HasControls() && (this._occasionalFields.NamedControls == null)) { /// Cette méthode va au final appeler la méthode FillNamedControlsTable qui est /// une fonction récursive ajoutant dans le dictionnaire _occasionalFields.NamedControls /// tous les contrôles enfants à l'exception des enfants des contrôle implémentant /// l'interface INamingContainer ou des contrôles dont l'id n'a pas été spécifié. this.EnsureNamedControlsTable(); } int num = id.IndexOfAny(new char[] { '$', ':' }); /// si l'id ne contient pas le caractère $ ou : alors on retourne directement le contrôle /// présent dans le namingcontainer en cours if (num == -1) { // retourne l'élément demandé du dictionnaire return (this._occasionalFields.NamedControls[id] as Control); } /// sinon on cherche le contrôle "parent" puis on recherche via la méthode FindControl /// l'id sur le contrôle "parent". En vrai c'est implémenté différemment mais /// c'est l'idée qu'il faut retenir else { return ((Control)this._occasionalFields.NamedControls[id]).FindControl( id.Substring(num + 1,id.Length - num)); } }

La première chose intéressante est que la méthode FindControl recherche les contrôles contenus par les NamingContainer c'est à dire les contrôles qui implémente INamingContainer. La seconde chose, est que si l'on veut faire une recherche d'un namingcontrol à un autre on peut avoir une notion de hiérarchie en utilisant les symboles $ ou : pour séparer les contrôles.

Par exemple le contrôle Login implémente INamingContainer puisqu'il hérite de CompositeControl. Ce contrôle est constitué de différentes textbox. Si l'on veut récupérer l'instance d'une textbox on peut alors faire :

// contient l'instance de la textbox du password contenu dans le controle login TextBox tbPassword = (TextBox)Page.FindControl("login1:Password");

Lorsque l'on définit un trigger sur un UpdatePanel :

<Triggers> <asp:AsyncPostBackTrigger ControlID="btn1" /> </Triggers>

On utilise au final la méthode ControlUtil.FindTargetControl :

internal static Control FindTargetControl(string controlID, Control control, bool searchNamingContainers) { if (searchNamingContainers) { Control namingContainer = control; Control control2 = null; while ((control2 == null) && (namingContainer != control.Page)) { namingContainer = namingContainer.NamingContainer; if (namingContainer == null) { return control2; } control2 = namingContainer.FindControl(controlID); } return control2; } return control.FindControl(controlID); }

Le paramètre controlID correspond à la valeur de la propriété ControlID, control est l'UpdatePanel sur lequel on a ajouté le trigger et searchNamingContainers est vrai dans le cas d'un AsyncPostBackTrigger et faux dans le cas d'un PostBackTrigger. Lorsqu'on utilise un AsyncPostBackTrigger on se rend alors compte que la recherche se fait en remontant les NamingContainer.

Posted: samedi 23 juin 2007 17:54 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

Jacksparoow a dit :

merci cyril pour cet article ça aide bouceaup sauf que j'ai une question à propos de cette recherche de control est ce que le trigger de l'updatepanel est capable de trouver un control qui exsite dans un autre NaminContainer?

merci

# mai 10, 2008 21:01

cyril a dit :

Ta question n'est pas assez précise, quelle genre de trigger, un asyncpostbacktrigger ou un postbacktrigger ?

Dans le cas d'un AsyncPostBackTrigger, l'UpdatePanel recherche d'abord via FindContrl dans son NamingContainer, s'il ne le trouve pas, il va chercher dans le namingContainer du namingContainer et ainsi de suite.

Tout est expliqué dans ce post, qui est en effet un poil technique :-)

# mai 10, 2008 22:44
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- TechDays Paris 2010 : La BI dans SharePoint 2010 par Blog Technique de Romelard Fabrice le il y a 43 minutes

- TechDays Paris 2010 : Déploiement de nouvelles technologies – Retour d’expérience par l’informatique de Microsoft par Blog Technique de Romelard Fabrice le il y a 2 heures et 10 minutes

- TechDays Paris 2010 : Plan de migration vers SharePoint 2010 par Blog Technique de Romelard Fabrice le il y a 5 heures et 52 minutes

- TechDays Paris 2010 : La pleinière du second jour par Blog Technique de Romelard Fabrice le il y a 6 heures et 58 minutes

- Visual Studio 2010 and .NET Framework 4 Release Candidate now available par Matthieu MEZIL le il y a 10 heures et 3 minutes

- Création d’une base de donnée sous SQL Azure par Le Blog (Vert) d'Arnaud JUND le il y a 11 heures et 0 minutes

- TechDays Paris 2010 : Les Services d’applications dans SharePoint 2010 par Blog Technique de Romelard Fabrice le il y a 20 heures et 59 minutes

- TechDays Paris 2010 : La GED et SharePoint 2010 par Blog Technique de Romelard Fabrice le 02-08-2010, 16:54

- TechDays Paris 2010 : SharePoint 2010 et Les réseaux sociaux par Blog Technique de Romelard Fabrice le 02-08-2010, 15:40

- TechDays Paris 2010 : SharePoint 2010 – Description et nouveautés par Blog Technique de Romelard Fabrice le 02-08-2010, 14:33