web-dev-qa-db-ja.com

フォームC#のすべてのコントロールをクリアするための最良の方法は何ですか?

しばらく前に誰かがこれらの線に沿って何かを尋ねたのを見たのを覚えていますが、検索したところ何も見つかりませんでした。

フォーム上のすべてのコントロールをクリアしてデフォルトに戻す最もクリーンな方法を考え出そうとしています(たとえば、テキストボックスをクリアする、チェックボックスをオフにする)。

これについてどうしますか?

14
Nathan W

私がこれまでに思いついたのは、次のようなものです。

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

現時点では、トップレベルのコントロールのみを処理し、グループボックスやパネルを掘り下げることはありません。

17
Nathan W

私はその古い質問を知っていますが、たった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);

他のタイプのコントロールに拡張できます。あなたはそれをキャストする必要があります。

4
Isuru

上記のソリューションは、ネストされたコントロールを無視しているようです。

次のような再帰関数が必要になる場合があります。

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

コントロールの種類を確認せずに、Textプロパティをクリアするだけでは不十分です。

派生コントロールのセットにIClearable(Bill Kによって提案された)などのインターフェイスを実装すると、この関数の長さが短縮されますが、各コントロールでより多くの作業が必要になります。

2
benPearce

あなたは制御のためにループすることができます

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

私はネイサンの解決策に投票しましたが、コメントで処理できる以上のことを追加したいと思いました。

彼は実際には非常に優れていますが、GUIに追加する前に、追加する可能性のある各コントロールタイプをサブクラス化するのが最善の解決策だと思います。それらすべてに「Clearable」などのインターフェースを実装してもらい(私はJavaプログラマーですが、概念はそこにあるはずです))、「Clearable」オブジェクトのコレクションとして繰り返し処理します。 、それぞれで唯一のメソッド.clear()を呼び出す

これは、GUIが実際にOOシステムで実行される方法です。これにより、将来、コードを簡単に拡張できるようになります。ほとんど簡単すぎると、ショックを受けるでしょう。

編集: (既存のコントロールを変更しないことについてのネイサンのコメントによる)

おそらく、コントロールを参照する「コンテナ」クラスを作成できます(コントロールのタイプごとに1つ)。回答で設定したようなループでは、正しいコンテナーをインスタンス化し、コンテナー内に実際のコントロールを配置して、コンテナーをコレクションに格納できます。

そうすれば、コレクションの反復に戻ることができます。

これは、あなたが提案したものよりもはるかに複雑ではありませんが、無限に拡張可能な、優れた単純なソリューションです。

2
Bill K

これは最初の回答で提案したものと同じですが、VBでは、VB10を取得するまで、これがVBで実行できる最善の方法です。これは、ラムダで非戻り関数をサポートしていないためです。

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で同じことをする方法を見ることができるように、私はこれをここに投稿しています。

2
Nathan W

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

1
shahramvafadar

以下は、ITextBoxを実装するコントロールのtypeからテキストをクリアするために使用するメソッドです。

この例では、デフォルトのブール値が設定されていることに気づきました。ブールコンポーネントのデフォルト値を設定するように変更できると確信しています。

Clearメソッドにコントロールタイプ(TextBox、Label ...など)とコントロールコレクションを渡すと、ITextBoxを実装するコントロールからすべてのテキストがクリアされます。

このようなもの:

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

Clearメソッドは、ページまたはマスターページを対象としています。コントロールコレクションのタイプは異なる場合があります。すなわち。フォーム、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;
        }
    }
0
Chuck Conway