ASP.Net FindControl ne fonctionne pas - pourquoi?

j'ai utilisé FindControl dans le passé, avant .NET 2.0/3.0. Il semble que maintenant, pour une raison quelconque, les pièces D'identité de mes contrôles obtiennent un funky nommé assigné. Par exemple, j'ai assigné un id "cbSelect" à une case à cocher, mais FindControl ne le trouve pas. Quand je regarde le HTML il a été assigné ctl00_bodyPlaceHolder_ctl02_cbSelect.

Je n'ai trouvé aucun exemple de FindControl qui mentionne cela. En fait, tout le monde semble utiliser find control comme d'habitude.

alors, est-ce que je fais quelque chose de mal? N' .Net le changement? Quelqu'un peut jeter un peu de lumière sur ce, pour moi, c'est vraiment frustrant!

27
demandé sur Gavin Miller 2009-04-29 00:21:20

7 réponses

vous utilisez probablement une page maître ou des commandes utilisateur (ascx) et c'est la raison pour laquelle les ID du client changent. Imaginez que vous avez un contrôle dans la page principale avec le même id que celui dans la page. Il en résulterait des affrontements. Les changements d'id garantissent que toutes les propriétés ClientID sont uniques sur une page.

FindControl doit faire l'objet d'une attention particulière lors de L'utilisation de MasterPages. Jetez un oeil à ASP.NET 2.0 MasterPages et FindControl(). Le FindControl fonctionne à l'intérieur d'un nom du conteneur. La page D'accueil et la page sont des conteneurs de nommage différents.

28
répondu Aleris 2009-04-28 20:37:53

Vous pouvez écrire extender pour trouver n'importe quel contrôle sur la page en utilisant récursion. Cela pourrait être dans une classe Util/Helper.

 public static Control FindAnyControl(this Page page, string controlId)
    {
        return FindControlRecursive(controlId, page.Form);
    }

    public static Control FindAnyControl(this UserControl control, string controlId)
    {
        return FindControlRecursive(controlId, control);
    }

    public static Control FindControlRecursive(string controlId, Control parent)
    {
        foreach (Control control in parent.Controls)
        {
            Control result = FindControlRecursive(controlId, control);
            if (result != null)
            {
                return result;
            }
        }
        return parent.FindControl(controlId);
    }
8
répondu nemke 2013-09-27 12:58:31

j'ai eu assez de chance de travailler autour de ce problème dans "la plupart" des cas avec une méthode d'extension simple

Vous pouvez l'appeler sur n'importe quel contrôle de conteneur de niveau supérieur que vous pensez le mieux, y compris la Page elle-même si vous voulez scanner toute la hiérarchie de contrôle.

private static Control FindControlIterative(this Control control, string id)
{
    Control ctl = control;

    LinkedList<Control> controls = new LinkedList<Control>();

    while(ctl != null)
    {
        if(ctl.ID == id)
        {
            return ctl;
        }

        foreach(Control child in ctl.Controls)
        {
            if(child.ID == id)
            {
                return child;
            }

            if(child.HasControls())
            {
                controls.AddLast(child);
            }
        }

        ctl = controls.First.Value;
        controls.Remove(ctl);
    }

    return null;
}
8
répondu Stephen M. Redd 2018-10-02 01:40:12

lors de la recherche d'un contrôle dans une collection de contrôle, Utilisez toujours l'id que vous avez assigné au contrôle, pas celui que vous voyez dans le rendu du post source. Si FindControl () ne trouve pas le contrôle que vous savez exister, il y a de fortes chances que vous ne cherchiez pas dans la bonne branche de la hiérarchie de contrôle. Une fonction récursive a été un succès pour moi.

Voici mon exemple de ce que j'utilise pour VB.NET 3.5:

Function FindControlRecursive(ByVal ctrl As Control, ByVal id As String) As Control
    Dim c As Control = Nothing

    If ctrl.ID = id Then
        c = ctrl
    Else
        For Each childCtrl In ctrl.Controls
            Dim resCtrl As Control = FindControlRecursive(childCtrl, id)
            If resCtrl IsNot Nothing Then c = resCtrl
        Next
    End If

    Return c
End Function
Dim form HtmlForm = CType(FindControlRecursive(Me, "Form"), HtmlForm)
7
répondu George 2010-03-02 20:57:02

C'est la VB.NET code qui a fonctionné pour moi:

<Extension()> _
Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control
    If controlToStartWith Is Nothing Then Return Nothing
    If controlToStartWith.ID = controlIdToFind Then Return controlToStartWith
    For Each childControl As Control In controlToStartWith.Controls
        Dim resCtrl As Control = FindChildControlById(childControl, controlIdToFind)
        If resCtrl IsNot Nothing Then Return resCtrl
    Next childControl
    Return Nothing
End Function ' Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control

le crédit va à George pour l'initiale VB.NET code. Je ne l'ai modifié qu'un tout petit peu, avec 2 changements fonctionnels: mine ne fait pas d'erreur si/quand null/Nothing est passé en tant que contrôle d'entrée, et mine est implémentée en tant qu'Extension. Mes 3 autres modifications mineures n'affectent pas la fonctionnalité, mais pour moi, elles étaient des simplifications de code. Mais je sais que c'est très subjectif.

cette méthode peut donc être utilisée avec:

Dim c1 As Control = Page.FindChildControlById("aspControlID")

et si vous voulez le convertir en une classe spécifique d'enfant D'un contrôle, comme ceci:

Dim c1 As Control = Page.FindChildControlById("aspControlID")
Dim c As HyperLink = TryCast(c1, HyperLink)

mise à jour: ma fonction S'appelle maintenant 'FindChildControlById' (auparavant 'FindMiControl'). Je préférais la suggestion de SpeedNet.

3
répondu Shawn Kovac 2017-06-14 19:56:03

quand il rend le html, ASP.NET préfixe toutes les ID de contrôle avec les Id des conteneurs de nom (contrôle de L'utilisateur, etc..) dans une hiérarchie remontant jusqu'à la racine du document. Cela garantit que tous les ID sont uniques pour les dos de poteau, etc..

ceci n'affecte pas L'utilisation de FindControl où vous devez utiliser L'ID dans le markup original.

1
répondu Nick 2009-04-28 20:31:37

Voici une référence sur la façon dont les contrôles de formulaires web sont nommés...

Formulaires Web Identification Du Contrôle

0
répondu George 2009-04-28 20:32:37