画像ファイル
画像ファイル コントロールの配列をインデクサで処理する
VB.NET C#全般
1羊の皮を着た狼 VB.NET
2Form1、Form2の相互参照
3Form1、Form2の相互参照 2
4VB.NET C# データ型の基本
5VB.NET C# 文字列
6VB.NET タイマー精度
7BackgroundWorkerの魅力1..
8BackgroundWorkerの魅力2..
9VB6のタイマー
10コントロールの配列をインデクサ..
11コントロールの配列はジェネリク..
12インデクサ(C#、VB.NET)
13インデクサでBit操作
14Unicode 入門
15デリゲート入門
16マルチスレッド入門
17イベント入門
18デリゲートとイベント
18インターフェースの基本

RichTextBox関係
1RichTextBoxの不思議
2テキスト色付け高速化計画
3VB.NET RichTextBox1
4VB.NET RichTextBox 2

RS-232C関係
1RS-232Cの基礎
2RS-232Cの何が変わった..
3SerialPortクラス
4Unicode(ユニコード)の壁
5マルチスレッドの壁
6RS-232C サンプルコード
7RS-232CのHEXモニタ
8RS-232C 送信モジュール
9RS-232Cのループテスト
10RS-232Cのピンチェンジ..

Socket通信
1C#、VB2005 でSocket通信
2サーバー 複数接続

プロセス間通信
1プロセス間通信(送信側)
2プロセス間通信(受信側)


質問、意見はこちらに
画像ファイル

ブログ
画像ファイル
本だけ持って

VB.NET、C# コントロール配列
VB6を使ったことの有るプログラマーが最初にVB.NETを使用して疑問に思うのは、
どのようにするとコントロールの配列が可能となるかと言うことである。
コントロールとは何かと言う、厳密な定義は抜きにしても、それに対する大方の
回答はオブジェクトの配列を使用しなさいと言うアドバイスである。
ここでは配列を使わずに、あたかも配列であるかのごとく、コントロールを
扱う方法を考えてみる。

仕様
先ずフォームであるが、ラベルとテキストボックス,ボタンを6個づつ置いてある。
位置は適当で、実行時にコードで位置合わせをする。
画像ファイル

フォームロード時のコード
C# のコード
public Form1()
{
InitializeComponent();
SetControl();
}
private void SetControl()
{
//ラベルの左スパンと上スパン
const int intOffsetX = 10;
const int intOffsetY = 10;
//コントロールの高さと幅
const int intHeight = 20;
const int intWidth = 100;
//コントロールとコントロールのスパン
const int intVspan = 40 ;
const int intHspan = 10;

//コントロールの位置を設定
for (int i = 1 ; i<7; i++)
{
Label(i).SetBounds(intOffsetX, intVspan * (i - 1) +
intOffsetY, intWidth, intHeight);
Label(i).Text = "ラベル" + i.ToString();

//テキストボックスは2倍の幅を設定
TextBox(i).SetBounds(Label(1).Left + Label(1).Width + intHspan,
intVspan * (i - 1) + intOffsetY, intWidth * 2, intHeight);
TextBox(i).Text = String.Empty;
Button(i).SetBounds(TextBox(1).Left + TextBox(1).Width + intHspan,
intVspan * (i - 1) + intOffsetY, intWidth, intHeight);
Button(i).Text = "ボタン" + i.ToString();
      }

//イベントの追加
for (int i = 1 ;i < 7; i++)
{
Button(i).Click += Button_Click;
}
}

VB.NETのコード
    Private Sub Form1_Load(ByVal sender As System.Object,  _
ByVal
e As System.EventArgs)  _
Handles MyBase.Load
'ラベルの左スパンと上スパン
Const intOffsetX As Integer = 10, intOffsetY As Integer = 10
'コントロールの高さと幅
Const intHeight As Integer = 20, intWidth As Integer = 100
'コントロールとコントロールのスパン
Const intVspan As Integer = 40, intHspan As Integer = 10

'コントロールの位置を設定
For i As Integer = 1 To 6
With Label(i)
.SetBounds(intOffsetX, intVspan * (i - 1) + _
intOffsetY, intWidth, intHeight)
.Text = "ラベル" & i.ToString
End With
'テキストボックスは2倍の幅を設定
With TextBox(i)
.SetBounds(Label(1).Left + Label(1).Width + intHspan, _
intVspan * (i - 1) + intOffsetY, intWidth * 2, intHeight)
.Text = String.Empty
End With

With Button(i)
.SetBounds(TextBox(1).Left + TextBox(1).Width + intHspan, _
intVspan * (i - 1) + intOffsetY, intWidth, intHeight)
.Text = "ボタン" & i.ToString
End With
Next

'イベントの追加
For i As Integer = 1 To 6
AddHandler Button(i).Click, AddressOf Button_Click
Next

End Sub

上のコードはなるべくVB6のコントロールの配列のコードに似せてある。
「なーんだ何のへんてつもない、コントロールの配列を使った位置設定でじゃ無いですか」
と言われそうである、ところがこの Label(i)等は実は配列では無く関数呼び出しである。
「え!でも  With Label(i) などと Withまで使っていますが?」と言うかもしれない。
でもやはり配列ではないのだ、その証拠に6つずつ置かれているコントロール名はそれぞれ、
Label1 Label2 Label3 .... TextBox1 Textbox2 textbox3... Button1 Button2 Button3...
となっているのだ。
いったいどのようになっているのだろうか? そのヒミツは下のコードにある。
引数の番号を名前に持つコントロールを返す関数

C#のコード
//引数indexに番号を受け取って、その番号が付いたLabelコントロールを返す
private Label Label(int index )
{
return (Label)(this.Controls["Label" + index.ToString()]);
}

//引数indexに番号を受け取って、その番号が付いたTextBoxコントロールを返す
private TextBox TextBox(int index)
{
return (TextBox)(this.Controls["TextBox" + index.ToString()]);
}

//引数indexに番号を受け取って、その番号が付いたButtonコントロールを返す
private Button Button(int index)
{
return (Button)(this.Controls["Button" + index.ToString()]);
}

VB.NETのコード
    
'引数indexに番号を受け取って、その番号が付いたLabelコントロールを返す
Private Function Label(ByVal index As Integer) As Label
Return DirectCast(Me.Controls("Label" & index.ToString), Label)
End Function

'引数indexに番号を受け取って、その番号が付いたTextBoxコントロールを返す
Private Function TextBox(ByVal index As Integer) As TextBox
Return DirectCast(Me.Controls("TextBox" & index.ToString), TextBox)
End Function

'引数indexに番号を受け取って、その番号が付いたButtonコントロールを返す
Private Function Button(ByVal index As Integer) As Button
Return DirectCast(Me.Controls("Button" & index.ToString), Button)
End Function

上のコードは引数に番号をもらって、コントロール名の最後にその番号が付いたコントロール
そのものを返すのである。
つまりLabel(1)は実際は Label1が返ってきているのである。
ラベルばかりではなくテキストボックスも、ボタンも同じ書式で書かれている。
すなわち配列に見せかけた関数である。
関数の戻り値が、コントロールそのものであるので、殆どの処理が配列と同じ書式で書ける。
インデクサという言葉がある。
ウィキペディア(Wikipedia) インデクサ
要するに配列で無いものを配列に見せかけるコードである。
実はここに書いたコードはインデクサではない。
C#におけるインデクサは引数付きのプロパティであり、VB.NETはデフォルトプロパティ である。
これに関しては 「インデクサ」 を御覧戴きたい。
C#、VB.NETのコントロールをあたかも 配列のように扱うことが出来るのである。

各ボタンのイベントハンドラはC#は「+=」でVB.NETは「AddHandler」で簡単に追加出来る。
さて問題はボタンのクリックイベントでイベント元のコントロールの 取得には、イベントハンドラーに渡ってくるイベント元のオブジェクトをボタンクラスにキャストして、
そのボタンオブジェクトの名前から、名前に付いている番号を取得している。
ボタンクリック・イベントハンドラ
ボタンをクリックした時のイベントハンドラの処理は下のコードで簡単にイベントが追加出来る。
イベントに関しては 「イベントの入門」 を参照されたし。
C#のコード
Button(i).Click += Button_Click;
VB.NET
AddHandler Button(i).Click, AddressOf Button_Click


ボタンクリック・イベント
さて問題はボタンのクリックイベントでイベント元のコントロールの 取得には、イベントハンドラーに渡ってくるイベント元のオブジェクトをボタンクラスにキャストして、
そのボタンオブジェクトの名前から、名前に付いている番号を取得している。
C#のコード
private void  Button_Click(System.Object sender ,System.EventArgs e )
{
//イベントの送り側の名前を取得
string senderName = ((Button)(sender)).Name;

//ボタンのベース名 長さの取得に使用
string strBut = "Button";

//Buttonxxのxxを取得して数字に直している
int index = int.Parse(senderName.Substring(strBut.Length,
senderName.Length - strBut.Length));

//取得したインデックスで各ボタンのクリックイベントを処理
switch(index)
{
case 1:
TextBox(1).Text = "ボタン1が押されました";
break;
case 2:
TextBox(2).Text = "ボタン2が押されました";
break;
default:
TextBox(index).Text = "ボタン" + index.ToString() +"が押されました";
break;
}
}

VB.NET
    Private Sub Button_Click(ByVal sender As System.Object,  _
ByVal e As System.EventArgs)
'イベントの送り側の名前を取得
Dim senderName As String = DirectCast(sender, Button).Name

'ボタンのベース名 長さの取得に使用
Dim strBut As String = "Button"

'Buttonxxのxxを取得して数字に直している
Dim index As Integer = CInt(senderName.Substring(strBut.Length, _
senderName.Length - strBut.Length))

'取得したインデックスで各ボタンのクリックイベントを処理
Select Case index
Case 1
TextBox(1).Text = "ボタン1が押されました"
Case 2
TextBox(2).Text = "ボタン2が押されました"
Case Else
TextBox(index).Text = "ボタン" & index.ToString & "が押されました"
End Select
End Sub

よく目を凝らして見て欲しい、TextBox(1).Text TextBox(2).Text TextBox(index).Textも配列
では有りません、番号を引数にした関数呼び出しなのです。
このコードを使うに当たっては一つ注意が必要である、実際にコントロールについている数字以外を、
引数にして関数を呼び出してはいけない、もしその可能性が少しでもある場合は、例に依って適切に
エラー処理を入れる必要が有る。
画像ファイル