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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/297526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:09:12  来源:igfitidea点击:

What is the best way to clear all controls on a form C#?

c#controls

提问by Nathan W

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?

你会怎么做?

采纳答案by Nathan W

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.

目前它只会处理顶级控件,不会深入挖掘分组框和面板。

回答by Patrick Desjardins

You can loop for control

你可以循环控制

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

回答by Bill K

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 之前对您可能添加的每个控件类型进行子类化。让他们都实现一个接口“Clearable”或类似的东西(我是一个java程序员,但概念应该在那里),然后将它作为“Clearable”对象的集合进行迭代,调用唯一的方法 .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)

编辑:(根据 Nathan 关于不更改现有控件的评论)

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.

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

回答by Chuck Conway

Below are methods I use to clear text from a typeof 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 方法适用于 Page 或 Masterpage。控件集合类型可能会有所不同。IE。表单、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;
        }
    }

回答by benPearce

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 所建议的)将减少此函数的长度,但需要对每个控件进行更多的工作。

回答by Nathan W

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 中可以做的最好的事情,因为它不支持 lambdas 中的非返回函数:

VB Solution:

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

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 中做同样的事情。

回答by shahramvafadar

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

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

回答by Isuru

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.

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