2009-03-06 16 views
12

Tengo un formulario de contenido web y necesito acceder a un control dentro del panel de contenido. Conozco dos maneras de acceder al control de:Encontrar un control en un formulario web

  1. TextBox txt = (TextBox)Page.Controls[0].Controls[3].Controls[48].Controls[6]
  2. Al escribir una función recursiva que busca a través de todos los controles.

Hay otra manera más fácil, ya que Page.FindControl no funciona en esta instancia. La razón por la que estoy preguntando es que me parece que el objeto Page o el objeto Panel de contenido debe tener un método para encontrar un control secundario, pero no puede encontrar nada parecido.

Respuesta

26

El problema es que FindControl() no atraviesa ciertos controles secundarios como un control de plantilla. Si el control que está después vive en una plantilla, no se encontrará.

Por lo tanto, hemos agregado los siguientes métodos de extensión para solucionar esto. Si no está utilizando 3.5 o quiere evitar los métodos de extensión, podría crear una biblioteca de propósito general a partir de estos.

Ahora usted puede conseguir el control que está después de la codificación:

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

métodos de la extensión hacen el trabajo recursivo para usted. ¡Espero que esto ayude!

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, esto debería ser p ¡arte del Marco! – Marcel

0

me gustaría cambiar su función GetControls a un genérico de la siguiente manera:

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; 
} 

Y entonces,

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

De esta manera, la persona que llama llamaría algo así como:

var button = Page.GetControl<Button>("MyButton"); 
Cuestiones relacionadas