web-dev-qa-db-fra.com

Meilleure façon de trouver le contrôle dans ASP.NET

J'ai un formulaire asp.net complexe, ayant même 50 à 60 champs dans un formulaire comme il y a Multiview, à l'intérieur de MultiView j'ai un GridView, et à l'intérieur de GridView j'ai plusieurs CheckBoxes.

Actuellement, j'utilise le chaînage de la méthode FindControl() et la récupération de l'ID enfant.

Maintenant, ma question est qu'il existe une autre manière/solution pour trouver le contrôle imbriqué dans ASP.NET.

46
santosh singh

Si vous recherchez un type de contrôle spécifique, vous pouvez utiliser une boucle récursive comme celle-ci - http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol -recursive-with-generics.aspx

Voici un exemple que j'ai fait qui retourne tous les contrôles du type donné

/// <summary>
/// Finds all controls of type T stores them in FoundControls
/// </summary>
/// <typeparam name="T"></typeparam>
private class ControlFinder<T> where T : Control 
{
    private readonly List<T> _foundControls = new List<T>();
    public IEnumerable<T> FoundControls
    {
        get { return _foundControls; }
    }    

    public void FindChildControlsRecursive(Control control)
    {
        foreach (Control childControl in control.Controls)
        {
            if (childControl.GetType() == typeof(T))
            {
                _foundControls.Add((T)childControl);
            }
            else
            {
                FindChildControlsRecursive(childControl);
            }
        }
    }
}
72
jimmystormig

Tard comme d'habitude. Si quelqu'un est toujours intéressé par cela, il existe un certain nombre de SO questions et réponses . Ma version de la méthode d'extension récursive pour résoudre ce problème) :

public static IEnumerable<T> FindControlsOfType<T>(this Control parent)
                                                        where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is T)
        {
            yield return (T)child;
        }
        else if (child.Controls.Count > 0)
        {
            foreach (T grandChild in child.FindControlsOfType<T>())
            {
                yield return grandChild;
            }
        }
    }
}
17
David Clarke

Toutes les solutions mises en évidence utilisent la récursivité (ce qui est coûteux en termes de performances). Voici une manière plus propre sans récursivité:

public T GetControlByType<T>(Control root, Func<T, bool> predicate = null) where T : Control 
{
    if (root == null) {
        throw new ArgumentNullException("root");
    }

    var stack = new Stack<Control>(new Control[] { root });

    while (stack.Count > 0) {
        var control = stack.Pop();
        T match = control as T;

        if (match != null && (predicate == null || predicate(match))) {
            return match;
        }

        foreach (Control childControl in control.Controls) {
           stack.Push(childControl);
        }
    }

    return default(T);
}
9
Ondrej Svejdar

FindControl ne recherche pas récursivement dans les contrôles imbriqués. Il ne trouve que les contrôles qui NamigContainer est le contrôle sur lequel vous appelez FindControl.

Il y a une raison pour laquelle ASP.Net ne regarde pas récursivement vos contrôles imbriqués par défaut:

  • Performance
  • Éviter les erreurs
  • Réutilisabilité

Considérez que vous souhaitez encapsuler vos GridViews, Formviews, UserControls, etc. à l'intérieur d'autres UserControls pour des raisons de réutilisabilité. Si vous aviez implémenté toute la logique dans votre page et accédé à ces contrôles avec des boucles récursives, il sera très difficile de refactoriser cela. Si vous avez implémenté votre logique et vos méthodes d'accès via les gestionnaires d'événements (par exemple RowDataBound de GridView), ce sera beaucoup plus simple et moins sujet aux erreurs.

6
Tim Schmelter

J'ai décidé de simplement construire des dictionnaires de contrôles. Plus difficile à maintenir, peut s'exécuter plus rapidement que le FindControl récursif ().

protected void Page_Load(object sender, EventArgs e)
{
  this.BuildControlDics();
}

private void BuildControlDics()
{
  _Divs = new Dictionary<MyEnum, HtmlContainerControl>();
  _Divs.Add(MyEnum.One, this.divOne);
  _Divs.Add(MyEnum.Two, this.divTwo);
  _Divs.Add(MyEnum.Three, this.divThree);

}

Et avant que je ne me trompe pour ne pas avoir répondu à la question du PO ...

Q: Maintenant, ma question est la suivante: existe-t-il un autre moyen/solution pour trouver le contrôle imbriqué dans ASP.NET? R: Oui, évitez en premier lieu de les rechercher. Pourquoi chercher des choses que vous savez déjà? Mieux vaut construire un système permettant référence des objets connus .

1
B H

Recherchez récursivement tous les contrôles correspondant au prédicat spécifié (n'incluez pas le contrôle racine):

    public static IEnumerable<Control> FindControlsRecursive(this Control control, Func<Control, bool> predicate)
    {
        var results = new List<Control>();

        foreach (Control child in control.Controls)
        {
            if (predicate(child))
            {
                results.Add(child);
            }
            results.AddRange(child.FindControlsRecursive(predicate));
        }

        return results;
    }

Usage:

myControl.FindControlsRecursive(c => c.ID == "findThisID");
1
DavidWainwright

Gestion des actions sur les contrôles

Créez la classe ci-dessous dans la classe de base. Classe Pour obtenir tous les contrôles:

public static class ControlExtensions
{
    public static IEnumerable<T> GetAllControlsOfType<T>(this Control parent) where T : Control
    {
        var result = new List<T>();
        foreach (Control control in parent.Controls)
        {
            if (control is T)
            {
                result.Add((T)control);
            }
            if (control.HasControls())
            {
                result.AddRange(control.GetAllControlsOfType<T>());
            }
        }
        return result;
    }
}

De la base de données: obtenez toutes les ID d'actions (comme divAction1, divAction2 ....) dynamiques dans DATASET (DTActions) autorisent un utilisateur spécifique.

Dans Aspx: dans HTML Put Action (bouton, ancre, etc.) en div ou span et donnez-leur l'id comme

<div id="divAction1" visible="false" runat="server" clientidmode="Static">   
                <a id="anchorAction" runat="server">Submit
                        </a>                      
                 </div>

IN CS: Utilisez cette fonction sur votre page:

private void ShowHideActions()
    {

        var controls = Page.GetAllControlsOfType<HtmlGenericControl>();

        foreach (DataRow dr in DTActions.Rows)
        {          

            foreach (Control cont in controls)
            {

                if (cont.ClientID == "divAction" + dr["ActionID"].ToString())
                {
                    cont.Visible = true;
                }

            }
        }
    }
1
atif

L'exemple suivant définit un gestionnaire d'événements Button1_Click. Lorsqu'il est appelé, ce gestionnaire utilise la méthode FindControl pour localiser un contrôle avec une propriété ID de TextBox2 sur la page contenant. Si le contrôle est trouvé, son parent est déterminé à l'aide de la propriété Parent et l'ID du contrôle parent est écrit dans la page. Si TextBox2 est introuvable, "Control Not Found" est écrit sur la page.

private void Button1_Click(object sender, EventArgs MyEventArgs)
{
      // Find control on page.
      Control myControl1 = FindControl("TextBox2");
      if(myControl1!=null)
      {
         // Get control's parent.
         Control myControl2 = myControl1.Parent;
         Response.Write("Parent of the text box is : " + myControl2.ID);
      }
      else
      {
         Response.Write("Control not found");
      }
}
0
Sudhakar Rao