清除C#表单上所有控件的最佳方法是什么?

时间:2021-06-18 16:00:25

I do remember seeing someone ask something along these lines a while ago but I did a search and couldn't find anything.

我记得前段时间有人问过这些问题,但是我做了一次搜索而找不到任何东西。

I'm trying to come up with the cleanest way to clear all the controls on a form back to their defaults (e.g., clear textboxes, uncheck checkboxes).

我正在尝试用最干净的方法将表单上的所有控件清除回默认值(例如,清除文本框,取消选中复选框)。

How would you go about this?

你会怎么做?

8 个解决方案

#1


17  

What I have come up with so far is something like this:

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

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

    }

}

Now you can just call the extension method ClearControls like this:

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

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

EDIT: I have just added a generic ClearControls method that will clear all the controls of that type, which can be called like this:

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

this.Controls.ClearControls<TextBox>();

At the moment it will only handle top level controls and won't dig down through groupboxes and panels.

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

#2


3  

I know its an old question but just my 2 cents in. This is a helper class I use for form clearing.

我知道这是一个老问题,但只是我的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;
                }
            }
        }
    }
}

And I call the method from any form like this passing a form object as a parameter.

我从任何形式调用方法,将表单对象作为参数传递。

Helper.ClearFormControls(this);

You can extend it for other types of controls. You just have to cast it.

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

#3


2  

You can loop for control

你可以循环控制

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

#4


2  

I voted for Nathan's solution, but wanted to add a bit more than a comment can handle.

我投票赞成了Nathan的解决方案,但想补充一点,而不是评论可以处理。

His is actually very good, but I think the best solution would involve sub-classing each of the control types you might be adding before adding them to the GUI. Have them all implement an interface "Clearable" or something like that (I'm a java programmer, but the concept should be there), then iterate over it as a collection of "Clearable" objects, calling the only method .clear() on each

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

This is how GUIs really should be done in an OO system. This will make your code easy to extend in the future--almost too easy, you'll be shocked.

这就是如何在OO系统中完成GUI。这将使您的代码在将来易于扩展 - 几乎太容易了,您会感到震惊。

Edit: (per Nathan's comment about not changing existing controls)

编辑:(根据内森关于不改变现有控制的评论)

Perhaps you could create "Container" classes that reference your control (one for each type of control). In a loop like the one you set up in your answer, you could instantiate the correct container, place the real control inside the container and store the container in a collection.

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

That way you are back to iterating over a collection.

这样你就可以重新迭代一个集合了。

This would be a good simple solution that isn't much more complex than the one you suggested, but infinitely more expandable.

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

#5


2  

The above solutions seem to ignore nested controls.

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

A recursive function may be required such as:

可能需要递归函数,例如:

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

You don't want to just clear the Text property without checking the controls type.

您不希望在不检查控件类型的情况下清除Text属性。

Implementing an interface, such as IClearable (as suggested by Bill K), on a set of derived controls would cut down the length of this function, but require more work on each control.

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

#6


2  

Here is the same thing that I proposed in my first answer but in VB, until we get VB10 this is the best we can do in VB because it doesn't support non returning functions in lambdas:

这是我在第一个答案中提出的相同的东西,但在VB中,直到我们得到VB10,这是我们在VB中可以做的最好的,因为它不支持lambda中的非返回函数:

VB Solution:

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

I'm just posting this here so that people can see how to do the same thing in VB.

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

#7


1  

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

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

#8


0  

Below are methods I use to clear text from a type of control that implements ITextBox.

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

I noticed in the example default boolean values are set. I'm sure you can modify it to set default values of boolean components.

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

Pass the Clear method a control type (TextBox, Label... etc) and a control collection, and it will clear all text from controls that implement ITextBox.

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

Something like this:

像这样的东西:

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

The Clear method is meant for a Page or Masterpage. The control collection type may vary. ie. Form, ContentPlaceHolder.. etc

Clear方法适用于页面或母版页。控件集合类型可能有所不同。即。 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;
        }
    }

#1


17  

What I have come up with so far is something like this:

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

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

    }

}

Now you can just call the extension method ClearControls like this:

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

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

EDIT: I have just added a generic ClearControls method that will clear all the controls of that type, which can be called like this:

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

this.Controls.ClearControls<TextBox>();

At the moment it will only handle top level controls and won't dig down through groupboxes and panels.

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

#2


3  

I know its an old question but just my 2 cents in. This is a helper class I use for form clearing.

我知道这是一个老问题,但只是我的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;
                }
            }
        }
    }
}

And I call the method from any form like this passing a form object as a parameter.

我从任何形式调用方法,将表单对象作为参数传递。

Helper.ClearFormControls(this);

You can extend it for other types of controls. You just have to cast it.

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

#3


2  

You can loop for control

你可以循环控制

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

#4


2  

I voted for Nathan's solution, but wanted to add a bit more than a comment can handle.

我投票赞成了Nathan的解决方案,但想补充一点,而不是评论可以处理。

His is actually very good, but I think the best solution would involve sub-classing each of the control types you might be adding before adding them to the GUI. Have them all implement an interface "Clearable" or something like that (I'm a java programmer, but the concept should be there), then iterate over it as a collection of "Clearable" objects, calling the only method .clear() on each

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

This is how GUIs really should be done in an OO system. This will make your code easy to extend in the future--almost too easy, you'll be shocked.

这就是如何在OO系统中完成GUI。这将使您的代码在将来易于扩展 - 几乎太容易了,您会感到震惊。

Edit: (per Nathan's comment about not changing existing controls)

编辑:(根据内森关于不改变现有控制的评论)

Perhaps you could create "Container" classes that reference your control (one for each type of control). In a loop like the one you set up in your answer, you could instantiate the correct container, place the real control inside the container and store the container in a collection.

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

That way you are back to iterating over a collection.

这样你就可以重新迭代一个集合了。

This would be a good simple solution that isn't much more complex than the one you suggested, but infinitely more expandable.

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

#5


2  

The above solutions seem to ignore nested controls.

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

A recursive function may be required such as:

可能需要递归函数,例如:

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

You don't want to just clear the Text property without checking the controls type.

您不希望在不检查控件类型的情况下清除Text属性。

Implementing an interface, such as IClearable (as suggested by Bill K), on a set of derived controls would cut down the length of this function, but require more work on each control.

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

#6


2  

Here is the same thing that I proposed in my first answer but in VB, until we get VB10 this is the best we can do in VB because it doesn't support non returning functions in lambdas:

这是我在第一个答案中提出的相同的东西,但在VB中,直到我们得到VB10,这是我们在VB中可以做的最好的,因为它不支持lambda中的非返回函数:

VB Solution:

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

I'm just posting this here so that people can see how to do the same thing in VB.

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

#7


1  

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

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

#8


0  

Below are methods I use to clear text from a type of control that implements ITextBox.

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

I noticed in the example default boolean values are set. I'm sure you can modify it to set default values of boolean components.

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

Pass the Clear method a control type (TextBox, Label... etc) and a control collection, and it will clear all text from controls that implement ITextBox.

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

Something like this:

像这样的东西:

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

The Clear method is meant for a Page or Masterpage. The control collection type may vary. ie. Form, ContentPlaceHolder.. etc

Clear方法适用于页面或母版页。控件集合类型可能有所不同。即。 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;
        }
    }