例えば、フォームに"TextBox1"という名前のコントロールが配置されている時に、"TextBox1"という文字列でそのコントロールを検索する方法を考えます。
.NET Framework 2.0からは、ControlCollection.Findメソッドが追加されました。Findメソッドは、指定した値と同じNameプロパティを持つコントロールを探します。
以下のコードは、フォームクラス内に記述することにより、フォームに配置されているコントロールから"TextBox1"という名前のコントロールを探し、見つかれば、Textプロパティを変更するものです。
'TextBox1をさがす。子コントロールも検索する。 Dim cs As Control() = Me.Controls.Find("TextBox1", True) 'TextBox1が見つかれば、Textを変更する If cs.Length > 0 Then CType(cs(0), TextBox).Text += "*" End If
//TextBox1をさがす。子コントロールも検索する。 Control[] cs = this.Controls.Find("TextBox1", true); //TextBox1が見つかれば、Textを変更する if (cs.Length > 0) ((TextBox)cs[0]).Text += "*";
VB.NETでは大文字、小文字を区別せずに検索しますが、C#では区別して検索するようです。
このメソッドはあくまでコントロールのNameプロパティで検索するだけで、そのコントロールのメンバ名で探すわけではありません。Visual Studioを使用してすべてのコントロールを配置している場合は問題となることはまずないと思いますが、動的に自分でコントロールを配置した場合は、Nameプロパティを適当に設定しないと、検索されません。また、複数のコントロールが同じNameプロパティを持つ場合は、複数のコントロールが返されます。
同様の機能は、インデクサとしても提供されています。
'TextBox1をさがす。子コントロールは検索しない。 Dim c As Control = Me.Controls("TextBox1") 'TextBox1が見つかれば、Textを変更する If c IsNot Nothing Then CType(c, TextBox).Text += "*" End If
//TextBox1をさがす。子コントロールは検索しない。 Control c = this.Controls["TextBox1"]; //TextBox1が見つかれば、Textを変更する if (c != null) ((TextBox)c).Text += "*";
この場合は、戻り値がコントロールの配列とはなりませんので、複数のコントロールに同じNameがつけられているときは、そのうちどれかしか返されません。また、子コントロールまでは検索しません。
Nameプロパティではなく、メンバ名そのもので検索する方法は、以下の「リフレクションによる方法」をご覧ください。
.NET Framework 1.1以前で同様の事を行う方法は、こちらです。
Visual Studioのフォームデザイナなどを使ってフォームにコントロールを追加した時、C#では、コントロールの"(Name)"プロパティに指定された名前と同じ名前のフィールドがフォームクラスに追加され、このフィールドにそのコントロールのオブジェクトが格納されます。VB.NETでは、WithEventsが付いていると、フィールドの名前は"(Name)"の頭に"_"が付いた名前になり、"(Name)"はプロパティの名前となります。つまり、リフレクションを使ってフォームクラスのフィールドやプロパティを名前で探し、見つかればそのフィールドの値を取得するという方法で問題が解決できます。
フォームに配置されたコントロールを名前で探すメソッドの例(FindControlByFieldNameメソッド)を紹介します。
''' <summary> ''' フォームに配置されているコントロールを名前で探す ''' (フォームクラスのフィールドをフィールド名で探す) ''' </summary> ''' <param name="frm">コントロールを探すフォーム</param> ''' <param name="name">コントロール(フィールド)の名前</param> ''' <returns>見つかった時は、コントロールのオブジェクト。 ''' 見つからなかった時は、null(VB.NETではNothing)。</returns> Public Shared Function FindControlByFieldName( _ ByVal frm As Form, ByVal name As String) As Object 'まずプロパティ名を探し、見つからなければフィールド名を探す Dim t As System.Type = frm.GetType() Dim pi As System.Reflection.PropertyInfo = _ t.GetProperty(name, _ System.Reflection.BindingFlags.Public Or _ System.Reflection.BindingFlags.NonPublic Or _ System.Reflection.BindingFlags.Instance Or _ System.Reflection.BindingFlags.DeclaredOnly) If Not pi Is Nothing Then Return pi.GetValue(frm, Nothing) End If Dim fi As System.Reflection.FieldInfo = _ t.GetField(name, _ System.Reflection.BindingFlags.Public Or _ System.Reflection.BindingFlags.NonPublic Or _ System.Reflection.BindingFlags.Instance Or _ System.Reflection.BindingFlags.DeclaredOnly) If fi Is Nothing Then Return Nothing End If Return fi.GetValue(frm) End Function
/// <summary> /// フォームに配置されているコントロールを名前で探す /// (フォームクラスのフィールドをフィールド名で探す) /// </summary> /// <param name="frm">コントロールを探すフォーム</param> /// <param name="name">コントロール(フィールド)の名前</param> /// <returns>見つかった時は、コントロールのオブジェクト。 /// 見つからなかった時は、null(VB.NETではNothing)。</returns> public static object FindControlByFieldName(Form frm, string name) { System.Type t = frm.GetType(); System.Reflection.FieldInfo fi = t.GetField( name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly); if (fi == null) return null; return fi.GetValue(frm); }
次に、自分自身のフォームに配置されている"TextBox1"という名前のテキストボックスコントロールを探し、そのTextの内容を変更する例を示します。
'"TextBox1"という名前のコントロールを探す Dim tb As TextBox = _ CType(FindControlByFieldName(Me, "TextBox1"), TextBox) '"TextBox1"のTextの内容を変更する tb.Text = "*" + tb.Text
//"TextBox1"という名前のコントロールを探す TextBox tb = (TextBox) FindControlByFieldName(this, "TextBox1"); //"TextBox1"のTextの内容を変更する tb.Text = "*" + tb.Text;
.NET Framework 2.0以降では、ControlCollection.Findメソッドで同様のことができます。こちらをご覧ください。
Visual Studioのフォームデザイナでコントロールを追加すると、"(Name)"プロパティはそのコントロールのNameプロパティと同じになりますので、単純に指定された文字列のNameプロパティを持つコントロールを探す方法も考えられます。ただし、実際にそうなる保障はありませんので、この方法は確実ではありません。この方法によるサンプルは、「.NETプログラミング研究 第30号」で紹介しています。
(この記事は「.NETプログラミング研究 第30号」で紹介したものを編集したものです。)
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。