2009-03-06 5 views
12

J'ai une forme de contenu Web et ont besoin d'accéder à un contrôle à l'intérieur du panneau de contenu. Je connais deux façons d'accéder au contrôle:Trouver un contrôle dans un formulaire en ligne

  1. TextBox txt = (TextBox)Page.Controls[0].Controls[3].Controls[48].Controls[6]
  2. En écrivant une fonction récursive qui recherche à travers tous les contrôles.

Existe-t-il un autre moyen plus simple, puisque Page.FindControl ne fonctionne pas dans cette instance. La raison pour laquelle je pose la question est qu'il me semble que l'objet Page ou l'objet Panneau de contenu devrait avoir une méthode pour trouver un contrôle enfant, mais ne peut pas trouver quelque chose comme ça.

Répondre

26

Le problème est que FindControl() ne traverse pas certains enfants de contrôle tels qu'un contrôle basé sur un modèle. Si le contrôle que vous recherchez subsiste dans un modèle, il ne sera pas trouvé.

Nous avons donc ajouté les méthodes d'extension suivantes pour faire face à cela. Si vous n'utilisez pas la version 3.5 ou si vous voulez éviter les méthodes d'extension, vous pouvez en faire une bibliothèque à usage général.

Vous pouvez maintenant obtenir le contrôle que vous êtes après par le codage:

var button = Page.GetControl("MyButton") as Button; 

Les méthodes d'extension font le travail récursif pour vous. J'espère que cela t'aides!

public static IEnumerable<Control> Flatten(this ControlCollection controls) 
{ 
    List<Control> list = new List<Control>(); 
    controls.Traverse(c => list.Add(c)); 
    return list; 
} 

public static IEnumerable<Control> Flatten(this ControlCollection controls,  
    Func<Control, bool> predicate) 
{ 
    List<Control> list = new List<Control>(); 
    controls.Traverse(c => { if (predicate(c)) list.Add(c); }); 
    return list; 
} 

public static void Traverse(this ControlCollection controls, Action<Control> action) 
{ 
    foreach (Control control in controls) 
    { 
     action(control); 
     if (control.HasControls()) 
     { 
      control.Controls.Traverse(action); 
     } 
    } 
} 

public static Control GetControl(this Control control, string id) 
{ 
    return control.Controls.Flatten(c => c.ID == id).SingleOrDefault(); 
} 

public static IEnumerable<Control> GetControls(this Control control) 
{ 
    return control.Controls.Flatten(); 
} 
+1

Wow, cela devrait être p l'art du cadre! – Marcel

0

Je voudrais changer votre fonction GetControls à un générique comme suit:

public static T GetControl<T>(this Control control, string id) where T:Control 
{ 
    var result = control.Controls.Flatten(c => (c.GetType().IsSubclassOf(typeof(T))) && (c.ID == id)).SingleOrDefault(); 
    if (result == null) 
     return null; 
    return result as T; 
} 

Et puis,

public static Control GetControl(this Control control, string id) 
{ 
    return control.GetControl<Control>(id); 
} 

De cette façon, l'appelant appellerait quelque chose comme:

var button = Page.GetControl<Button>("MyButton"); 
Questions connexes