DOBON.NET

フォームに配置されているコントロールを名前で探す

例えば、フォームに"TextBox1"という名前のコントロールが配置されている時に、"TextBox1"という文字列でそのコントロールを検索する方法を考えます。

.NET Framework 2.0以降で、ControlCollection.Findを使用する方法

.NET Framework 2.0からは、ControlCollection.Findメソッドが追加されました。Findメソッドは、指定した値と同じNameプロパティを持つコントロールを探します。

以下のコードは、フォームクラス内に記述することにより、フォームに配置されているコントロールから"TextBox1"という名前のコントロールを探し、見つかれば、Textプロパティを変更するものです。

VB.NET
コードを隠すコードを選択
'TextBox1をさがす。子コントロールも検索する。
Dim cs As Control() = Me.Controls.Find("TextBox1", True)
'TextBox1が見つかれば、Textを変更する
If cs.Length > 0 Then
    CType(cs(0), TextBox).Text += "*"
End If
C#
コードを隠すコードを選択
//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プロパティを持つ場合は、複数のコントロールが返されます。

同様の機能は、インデクサとしても提供されています。

VB.NET
コードを隠すコードを選択
'TextBox1をさがす。子コントロールは検索しない。
Dim c As Control = Me.Controls("TextBox1")
'TextBox1が見つかれば、Textを変更する
If c IsNot Nothing Then
    CType(c, TextBox).Text += "*"
End If
C#
コードを隠すコードを選択
//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メソッド)を紹介します。

VB.NET
コードを隠すコードを選択
''' <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
C#
コードを隠すコードを選択
/// <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の内容を変更する例を示します。

VB.NET
コードを隠すコードを選択
'"TextBox1"という名前のコントロールを探す
Dim tb As TextBox = _
    CType(FindControlByFieldName(Me, "TextBox1"), TextBox)
'"TextBox1"のTextの内容を変更する
tb.Text = "*" + tb.Text
C#
コードを隠すコードを選択
//"TextBox1"という名前のコントロールを探す
TextBox tb = (TextBox) FindControlByFieldName(this, "TextBox1");
//"TextBox1"のTextの内容を変更する
tb.Text = "*" + tb.Text;

Nameプロパティを使用する方法

.NET Framework 2.0以降では、ControlCollection.Findメソッドで同様のことができます。こちらをご覧ください。

Visual Studioのフォームデザイナでコントロールを追加すると、"(Name)"プロパティはそのコントロールのNameプロパティと同じになりますので、単純に指定された文字列のNameプロパティを持つコントロールを探す方法も考えられます。ただし、実際にそうなる保障はありませんので、この方法は確実ではありません。この方法によるサンプルは、「.NETプログラミング研究 第30号」で紹介しています。

  • 履歴:
  • 2007/1/15 「.NET Framework 2.0以降で、ControlCollection.Findを使用する方法」を追加。
  • 2018/6/17 「Control c = this.Controls["TextBox1"];」のコメントが間違えていたのを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。
共有する

この記事への評価

この記事へのコメント

この記事に関するコメントを投稿するには、下のボタンをクリックしてください。投稿フォームへ移動します。通常のご質問、ご意見等は掲示板へご投稿ください。