2008-11-18 113 views
14

我确实记得在前段时间看到有人问这些问题,但是我做了一个搜索,找不到任何东西。清除C#表单上所有控件的最佳方法是什么?

我试图想出最清洁的方式来清除窗体上的所有控件返回其默认值(例如,清除文本框,取消选中复选框)。

你会怎么做呢?

回答

17

我已经想出到目前为止是这样的:

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

    } 

} 

现在,你可以调用扩展方法ClearControls这样的:

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

编辑:我只是增加了一个通用ClearControls方法将清除该类型的所有控件,可以这样调用:

this.Controls.ClearControls<TextBox>(); 

目前它只能处理顶层控件,不会通过组框和面板进行挖掘。

+0

一个迷人的例子!谢谢。 – BillW 2009-11-28 13:22:59

2

您可以循环控制

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

我正在做这种类型的方法,但我想找到一些少一些,如果..然后..碱基。 – 2008-11-18 01:06:32

2

我投Nathan的解决方案,但想补充一点多评论可以处理。

他实际上非常好,但我认为最好的解决方案将涉及在添加到GUI之前对您可能添加的每种控件类型进行子分类。让他们都实现一个接口“Clearable”或类似的东西(我是一个Java程序员,但概念应该在那里),然后作为“Clearable”对象的集合进行迭代,调用唯一的方法.clear()在每个

这是图形用户界面如何真的应该在面向对象系统中完成。这将使您的代码在未来更容易扩展 - 几乎很容易,您会感到震惊。

编辑:(每Nathan的约不改变现有控件评论)

也许你可以创建一个“容器”引用你的控制(每个类型的控件)类。在像你在答案中设置的循环中,你可以实例化正确的容器,将真正的控件放在容器中,并将容器存储在一个集合中。

这样你回来迭代集合。

这将是一个很好的简单解决方案,并不比您建议的复杂得多,但可以无限扩展。

+0

是+百万。始终,总是在将每个控件添加到项目之前对其进行细分。它可以让你稍后更容易地改变事情。 – 2008-11-18 01:24:49

+0

我想过整个子类的事情,但我只是重构一个旧项目,我不想重做UI。在未来的项目中,我将把所有的东西都分类。 – 2008-11-18 01:34:42

0

下面是我用来清除实现ITextBox的控件的类型中的文本的方法。

我注意到在这个例子中设置了默认的布尔值。我相信你可以修改它来设置布尔组件的默认值。

将Clear方法传递给控件类型(TextBox,Label ...等)和控件集合,它将清除实现ITextBox的控件的所有文本。

事情是这样的:

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

的清除方法是为一个页面或母版。控件集合类型可能会有所不同。即。 Form,ContentPlaceHolder ..等

 /// <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

上述解决方案似乎忽略嵌套控件。

递归函数可能需要如:

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

你不想只是清除文本属性而不检查控件的类型。

在一组派生控件上实现一个接口(如IClearable(如Bill K所建议的))会减少此函数的长度,但需要在每个控件上进行更多的工作。

2

这里是我在我的第一个答案,但在VB中提出了同样的事情,直到我们得到VB10这是我们可以在VB做的,因为它不支持lambda表达式返回非功能最好:

VB解决方案:

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 

呼叫:

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

我只是在这里张贴这个,让人们可以看到如何在VB中做同样的事情。

1

private void FormReset() { ViewState.Clear(); Response.Redirect(Request.Url.AbsoluteUri.ToString()); }

3

我知道它的一个老问题,但只是我的2美分。这是一个帮助类,我用于表单清除。

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

而且我以任何形式调用方法,像这样传递一个表单对象作为参数。

Helper.ClearFormControls(this); 

您可以将其扩展为其他类型的控件。你只需要施放它。

相关问题