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.

    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

- [PowerShell 3] Télécharger et installer la documentation en ligne par Blog de SPBrouillet (Pierrick BROUILLET) le il y a 18 heures et 39 minutes

- [#SharePoint 2010][#SQLServer 2012] AlwaysOn pour SharePoint (1/4) : Configuration (1ère partie)… par Le blog de Patrick [MVP SharePoint] le 05-16-2012, 12:10

- Job Day @MIC Brussels - .Net Developers on Mobile applications par Le Blog (Vert) d'Arnaud JUND le 05-15-2012, 20:26

- [SharePoint 2010] – SharePoint 2010, Windows (Server) 8 et des erreurs IIS sont dans une VM… par Blog de SPBrouillet (Pierrick BROUILLET) le 05-14-2012, 12:10

- [Event] Windows Azure dev Camp le 20 juin! par Fathi Bellahcene le 05-13-2012, 09:29

- Comment redimensionner une image avec WinRT : plusieurs solutions par Richard Clark le 05-11-2012, 15:43

- Event : Swiss SharePoint Club Meeting #20 à Yverdon par Blog Technique de Romelard Fabrice le 05-11-2012, 15:24

- Réflechissons un peu ce matin à propos des ORM par Richard Clark le 05-11-2012, 08:48

- #SharePoint Solutions Roadshow le 5 juin à Issy ! par Le blog de Patrick [MVP SharePoint] le 05-09-2012, 15:10

- SharePoint : Mes alertes ne marchent pas … Que faire ? Comment réparer ou agir ? par The Mit's Blog le 05-08-2012, 14:59