2008-11-18 20 views
14

Recuerdo haber visto a alguien preguntar algo en esta línea hace un tiempo, pero hice una búsqueda y no pude encontrar nada.¿Cuál es la mejor manera de borrar todos los controles en un formulario C#?

Estoy tratando de encontrar la forma más limpia de borrar todos los controles de un formulario a sus valores predeterminados (por ejemplo, borrar cuadros de texto, desmarcar casillas de verificación).

¿Qué le parece?

Respuesta

17

Lo que he encontrado hasta el momento es algo como esto:

public static class extenstions 
{ 
    private static Dictionary<Type, Action<Control>> controldefaults = new Dictionary<Type, Action<Control>>() { 
      {typeof(TextBox), c => ((TextBox)c).Clear()}, 
      {typeof(CheckBox), c => ((CheckBox)c).Checked = false}, 
      {typeof(ListBox), c => ((ListBox)c).Items.Clear()}, 
      {typeof(RadioButton), c => ((RadioButton)c).Checked = false}, 
      {typeof(GroupBox), c => ((GroupBox)c).Controls.ClearControls()}, 
      {typeof(Panel), c => ((Panel)c).Controls.ClearControls()} 
    }; 

    private static void FindAndInvoke(Type type, Control control) 
    { 
     if (controldefaults.ContainsKey(type)) { 
      controldefaults[type].Invoke(control); 
     } 
    } 

    public static void ClearControls(this Control.ControlCollection controls) 
    { 
     foreach (Control control in controls) 
     { 
      FindAndInvoke(control.GetType(), control); 
     } 
    } 

    public static void ClearControls<T>(this Control.ControlCollection controls) where T : class 
    { 
     if (!controldefaults.ContainsKey(typeof(T))) return; 

     foreach (Control control in controls) 
     { 
      if (control.GetType().Equals(typeof(T))) 
      { 
       FindAndInvoke(typeof(T), control); 
      } 
     }  

    } 

} 

Ahora usted puede llamar a los ClearControls método de extensión de esta manera:

private void button1_Click(object sender, EventArgs e) 
    { 
     this.Controls.ClearControls(); 
    } 

EDIT: acabo añadido una método ClearControls genérico que borrará todos los controles de ese tipo, que se pueden llamar así:

this.Controls.ClearControls<TextBox>(); 

Por el momento, solo controlará los controles de nivel superior y no buscará en los grupos de grupos y paneles.

+0

¡un ejemplo fascinante! Gracias. – BillW

2

Usted puede bucle para el control

foreach (Control ctrl in this) 
{ 
    if(ctrl is TextBox) 
     (ctrl as TextBox).Clear(); 
} 
+0

Estaba haciendo este tipo de enfoque, pero quería encontrar algo un poco menos si ... entonces ... la base. –

2

Voté por la solución de Nathan, pero quería añadir un poco más que un comentario puede manejar.

El suyo es realmente muy bueno, pero creo que la mejor solución sería subconcluir cada uno de los tipos de control que podría estar agregando antes de agregarlos a la GUI. Pídales a todos que implementen una interfaz "Clearable" o algo por el estilo (soy un programador de Java, pero el concepto debería estar allí), luego repítelo como una colección de objetos "Clearable", llamando al único método .clear() en cada

Así es como deberían hacerse las GUI en un sistema OO. Esto hará que su código sea fácil de extender en el futuro; casi demasiado fácil, se sorprenderá.

Editar: (por el comentario de Nathan acerca de no cambiar los controles existentes)

Tal vez usted podría crear "contenedor" clases que hacen referencia a su control (uno para cada tipo de control). En un ciclo como el que configuró en su respuesta, podría instanciar el contenedor correcto, colocar el control real dentro del contenedor y almacenar el contenedor en una colección.

De esta manera volverá a iterar sobre una colección.

Esta sería una buena solución simple que no es mucho más compleja que la que sugirió, pero infinitamente más ampliable.

+0

Sí + millones. Siempre, siempre, siempre subclase cada control antes de agregarlo a su proyecto. Te permite cambiar las cosas mucho más fácilmente más adelante. –

+0

Pensé en todo el asunto de la clase secundaria, pero solo estaba refabricando un proyecto anterior y no quería tener que volver a hacer la interfaz de usuario. En proyectos futuros, subclasificaré todo. –

+0

@Bill Tomaré en cuenta sus sugerencias. –

0

A continuación se muestran los métodos que uso para borrar texto de un tipo de control que implementa ITextBox.

Me di cuenta que en el ejemplo se establecen los valores booleanos predeterminados. Estoy seguro de que puede modificarlo para establecer valores predeterminados de componentes booleanos.

Pase el método Clear a un tipo de control (TextBox, Label ... etc) y una colección de control, y borrará todo el texto de los controles que implementan ITextBox.

Algo como esto:

//Clears the textboxes 
WebControlUtilities.ClearControls<TextBox>(myPanel.Controls); 

El método Clear es para una página o Maestra. El tipo de colección de control puede variar. es decir. Form, ContentPlaceHolder .. etc

 /// <summary> 
    /// Clears Text from Controls...ie TextBox, Label, anything that implements ITextBox 
    /// </summary> 
    /// <typeparam name="T">Collection Type, ie. ContentPlaceHolder..</typeparam> 
    /// <typeparam name="C">ie TextBox, Label, anything that implements ITextBox</typeparam> 
    /// <param name="controls"></param> 
    public static void Clear<T, C>(ControlCollection controls) 
     where C : ITextControl 
     where T : Control 
    { 
     IEnumerable<T> placeHolders = controls.OfType<T>(); 
     List<T> holders = placeHolders.ToList(); 

     foreach (T holder in holders) 
     { 
      IEnumerable<C> enumBoxes = holder.Controls.OfType<C>(); 
      List<C> boxes = enumBoxes.ToList(); 

      foreach (C box in boxes) 
      { 
       box.Text = string.Empty; 
      } 
     } 
    } 

    /// <summary> 
    /// Clears the text from control. 
    /// </summary> 
    /// <typeparam name="C"></typeparam> 
    /// <param name="controls">The controls.</param> 
    public static void ClearControls<C>(ControlCollection controls) where C : ITextControl 
    { 
     IEnumerable<C> enumBoxes = controls.OfType<C>(); 
     List<C> boxes = enumBoxes.ToList(); 

     foreach (C box in boxes) 
     { 
      box.Text = string.Empty; 
     } 
    } 
2

Las soluciones anteriores parecen ignorar los controles anidados.

Una función recursiva se puede requerir tales como:

public void ClearControl(Control control) 
{ 
    TextBox tb = control as TextBox; 
    if (tb != null) 
    { 
    tb.Text = String.Empty; 
    } 
    // repeat for combobox, listbox, checkbox and any other controls you want to clear 
    if (control.HasChildren) 
    { 
    foreach(Control child in control.Controls) 
    { 
     ClearControl(child) 
    } 
    } 
} 

Usted no quiere simplemente borrar la propiedad de texto sin comprobar el tipo de controles.

La implementación de una interfaz, como IClearable (como lo sugiere Bill K), en un conjunto de controles derivados reduciría la duración de esta función, pero requerirá más trabajo en cada control.

+0

La solución que presenté incluirá controles anidados. –

+0

Nathan, esa es una solución interesante. El aspecto anidado del código no era inmediatamente evidente al mirar el código, así que no lo vi. – benPearce

+0

Sí, está un poco escondido, pero oye, funciona bien –

2

aquí es la misma cosa que he propuesto en mi primera respuesta, pero en VB, hasta llegar VB10 este es el mejor que podemos hacer en VB, ya que no soporta las funciones no regresan en lambdas:

VB Solución:

Public Module Extension 
    Private Sub ClearTextBox(ByVal T As TextBox) 
     T.Clear() 
    End Sub 

    Private Sub ClearCheckBox(ByVal T As CheckBox) 
     T.Checked = False 
    End Sub 

    Private Sub ClearListBox(ByVal T As ListBox) 
     T.Items.Clear() 
    End Sub 

    Private Sub ClearGroupbox(ByVal T As GroupBox) 
     T.Controls.ClearControls() 
    End Sub 

    <Runtime.CompilerServices.Extension()> _ 
    Public Sub ClearControls(ByVal Controls As ControlCollection) 
     For Each Control In Controls 
      If ControlDefaults.ContainsKey(Control.GetType()) Then 
       ControlDefaults(Control.GetType()).Invoke(Control) 
      End If 
     Next 
    End Sub 

    Private _ControlDefaults As Dictionary(Of Type, Action(Of Control)) 
    Private ReadOnly Property ControlDefaults() As Dictionary(Of Type, Action(Of Control)) 
     Get 
      If (_ControlDefaults Is Nothing) Then 
       _ControlDefaults = New Dictionary(Of Type, Action(Of Control)) 
       _ControlDefaults.Add(GetType(TextBox), AddressOf ClearTextBox) 
       _ControlDefaults.Add(GetType(CheckBox), AddressOf ClearCheckBox) 
       _ControlDefaults.Add(GetType(ListBox), AddressOf ClearListBox) 
       _ControlDefaults.Add(GetType(GroupBox), AddressOf ClearGroupbox) 
      End If 
      Return _ControlDefaults 
     End Get 
    End Property 

End Module 

Calling:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     Me.Controls.ClearControls() 
    End Sub 

soy sólo publicar esto aquí para que las personas puedan ver cómo hacer lo mismo en VB.

1

vacío privado FormReset() { ViewState.Clear(); Response.Redirect (Request.Url.AbsoluteUri.ToString()); }

3

Sé que es una vieja pregunta, pero solo mis 2 centavos. Esta es una clase de ayuda que uso para borrar formularios.

using System; 
using System.Windows.Forms; 

namespace FormClearing 
{ 
    class Helper 
    { 
     public static void ClearFormControls(Form form) 
     { 
      foreach (Control control in form.Controls) 
      { 
       if (control is TextBox) 
       { 
        TextBox txtbox = (TextBox)control; 
        txtbox.Text = string.Empty; 
       } 
       else if(control is CheckBox) 
       { 
        CheckBox chkbox = (CheckBox)control; 
        chkbox.Checked = false; 
       } 
       else if (control is RadioButton) 
       { 
        RadioButton rdbtn = (RadioButton)control; 
        rdbtn.Checked = false; 
       } 
       else if (control is DateTimePicker) 
       { 
        DateTimePicker dtp = (DateTimePicker)control; 
        dtp.Value = DateTime.Now; 
       } 
      } 
     } 
    } 
} 

Y llamo el método de cualquier forma como esta pasando un objeto de formulario como un parámetro.

Helper.ClearFormControls(this); 

Puede ampliarlo para otros tipos de controles. Solo tienes que lanzarlo.

Cuestiones relacionadas