2010-05-19 25 views
5

¿Es posible borrar de forma dinámica (y genérica) el estado de todos los controles secundarios de un control de usuario? (Por ejemplo, todos sus cuadros de texto, botones de radio, DropDrownLists, DataGrids, repetidores, etc - básicamente cualquier cosa que tenga ViewState)¿Cómo puedo eliminar dinámicamente todos los controles en un control de usuario?

que estoy tratando de evitar hacer algo como esto:

foreach (Control c in myUserControl.Controls) 
{ 
    if (c is TextBox) 
    { 
     TextBox tb = (TextBox)c; 
     tb.Text = ""; 
    } 
    else if (c is DropDownList) 
    { 
     DropDownList ddl = (DropDownList)c; 
     ddl.SelectedIndex = -1; 
    } 
    else if (c is DataGrid) 
    { 
     DataGrid dg = (DataGrid)c; 
     dg.Controls.Clear(); 
    } 

    // etc. 

} 

estoy buscando algo como esto:

foreach (Control c in myUserControl.Controls) 
    c.Clear(); 

... pero obviamente eso no existe. ¿Hay alguna manera fácil de lograr esto de forma dinámica/genérica?

+0

Tal vez, todo lo que necesitas es un simple redireccionamiento? – Alex

Respuesta

3

Iba a sugerir una solución similar a Task excepto (como señala sixlettervariables) tenemos que implementarlo como 1 método de extensión e inmediatamente activar el tipo exacto del control pasado (es decir, copiar la lógica que publicaste en tu pregunta).

public static class ControlExtensions 
{ 
    public static void Clear(this Control c) 
    { 
     if(c == null) { 
      throw new ArgumentNullException("c"); 
     } 
     if (c is TextBox) 
     { 
      TextBox tb = (TextBox)c; 
      tb.Text = ""; 
     } 
     else if (c is DropDownList) 
     { 
      DropDownList ddl = (DropDownList)c; 
      ddl.SelectedIndex = -1; 
     } 
     else if (c is DataGrid) 
     { 
      DataGrid dg = (DataGrid)c; 
      dg.Controls.Clear(); 
     } 
     // etc.... 
    } 
} 

No es particularmente elegentPackage mirando método, pero su código en su página/control es ahora la más sucinta

foreach (Control c in myUserControl.Controls) { 
    c.Clear(); 
} 

y se puede, por supuesto, ahora llamar control.Clear() cualquier otro lugar en que código.

+0

Acepté esta respuesta porque creo que esto es lo más cercano que puedo llegar a mi intención original. Desafortunadamente, parece que no existe una forma perfectamente dinámica de borrar todos los controles secundarios. – Michael

1

Se puede hacer

foreach (Control c in myUserControl.Controls) { 
    myUserControl.Controls.Remove(c); 
} 

porque los controles es sólo una lista, puede llamar a remove() en él, pasándole lo que desea eliminar.

EDITAR: Oh, lo siento, no lo leí correctamente. No sé de una manera de hacer esto, tal vez alguien aquí que es bueno con la reflexión podría hacerlo donde se puede hacer como

foreach (Control c in myUserControl.Controls) { 
    c = new c.Type.GetConstructor().Invoke(); 
} 

o algo así, para convertirlo en un componente recién hecho.

+1

Creo que Michael está buscando borrar los valores/estado en cada control. No los controles de la colección. –

+0

KP: Correcto. No quiero * eliminar * los controles, simplemente borrarlos (por ej., Borrar un texto de TextBox, borrar el elemento seleccionado en DropDownList, borrar el contenido de un DataGrid/Repeater, etc.). – Michael

+0

Sí, lo siento, editado para reflejar mi mala lectura. – Nilbert

1

No lo he probado, pero la limpieza de viewstate para el control de usuario puede funcionar. Ya que podría exponer un método personalizado en el control de usuario, así:

usercontrol:

public void Clear() 
{ 
    this.ViewState.Clear(); 
} 

página:

myUserControlInstance.Clear(); 

Ahora, de nuevo no he probado. Es posible que esto solo borre el StateBag para el contenedor UserControl, y no sus controles anidados/secundarios ... si lo anterior no funciona, podría intentar usar recursividad para recorrer el árbol de control para borrar viewstate para todos los elementos secundarios:

usercontrol:

public void Clear() 
{ 
    ClearViewState(this.Controls); 
} 

private void ClearViewState(ControlCollection cc) 
{ 
    foreach(Control c in cc) 
    { 
     if(c.HasControls()) 
     { 
      //clear the child controls first 
      ClearViewState(c.Controls); 
     }   

     //then clear the control itself 
     c.ViewState.Clear(); 
    } 
} 

página:

myUserControlInstance.Clear(); 

Es sólo una idea. No lo he probado, pero creo que en teoría podría funcionar. Una implicación sería llamar a Clear en el punto correcto en el ciclo de vida de la página/controles, de lo contrario, puede que no funcione.

Espero que esto ayude!

+0

Hmmm ... lo probé yo mismo y parece que no funciona ... Lo jugaré un poco más, ya que me gusta el concepto ... –

+0

Salté el arma. 'ViewState' no es una propiedad pública, por lo que no puede despejarse para los controles. Me gusta la idea de recursión discutida en la otra respuesta ... Dejaré esta respuesta aunque no vaya a funcionar en caso de que otros piensen lo mismo ... –

0

Por qué no lo hacen como usted sugiere:

foreach (Control c in myUserControl.Controls) 
    c.Clear(); 

y luego implementar Claro:

public static class UserController 
{ 
    public static void Clear(this Control c) 
    { 
     c.Controls.Clear(); 
    } 

    public static void Clear(this TextBox c) 
    { 
     c.Text = String.Empty; 
    } 
} 

Eso debería hacerlo.

+0

-1, los métodos de extensión no hacen el despacho dinámico . – user7116

+0

Entonces cada llamada a Clear() en el foreach llamará a la estática Control.Clear()? Entonces, para que funcione, volvería al "if (c es TextBox) ..." dentro de Control.Clear()? De hecho, no es una buena solución entonces. – Task

+0

Correcto. 'c' está tipeado estáticamente como' Control', por lo que el método de extensión lo buscaría para 'Control'. – user7116

1
myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c)); 

Sin embargo, tenga cuidado, porque modifica la lista de iteración. Esto podría llevar a un comportamiento extraño.

+0

Menos 1 porque quitar controles no tiene nada que ver con la pregunta original. –

1

El ajuste EnableViewState="false" en los controles individuales puede ahorrarle trabajo, si no le causa otros problemas en este caso.

1

¿Qué tal el método Control.ClearChildViewState?

MSDN indica

elimina la información de estado de vista para todos los controles secundarios del control de servidor.

Nunca lo he usado. Entonces no estoy seguro si te ayudará. Suena bien, creo :)

+0

Parece que debería ser la solución perfecta, pero desafortunadamente no funciona. – Michael

Cuestiones relacionadas