VB.NETです。
TextBox1、TextBox2、TextBox3 のコントロールがあります。
これに
dim arrayStr() String = {"赤", "青", "黄"}
For i as Integer = 1 To 3
TextBox & i & .Text = arrayStr(i-1)
Next
よろしくお願いします。
文法的に間違っているコードを見せてただ「こんなこと」と言われても、
何をしたいのかを汲み取ることは非常にむずかしいと思います。
まずは文章できちんと「何をしたいか」を説明し、
その上で「こういうコードを書きましたが、
予想に反してXXになってしまいます」などと
書いたほうが、希望と問題点がはっきりしますよね。
やりたいことは、
コントロール配列を本当は使いたいですってことね。
VB6までは、確かに簡単にできましたが、
.NETからは、コントロール配列は利用できません。
ただし、方法はあります。
まずは、Googleで探してみてください。
誰かが同じことをしようとしているはずです。
すんませんでした。
どういうふうな言葉にしたらいいのか解らず
こう書いたほうが解りやすいかと勘違していました。
TextBox1.Text = "あいう"
の TextBox1 の数字「1」をネクスト文の中で
連続して代入できないかなと思ったのです
TextBox1 TextBox2 TextBox3 TextBox4 の
テキストプロパティにすべて 同じ言葉を入れたいのです。
検索のキーワード「コントロール配列」で調べて見ます。
調べて見ました。
コレクション変数 とか コントロール配列として追加したコントロールのイベントを取得 など
いろいろヒットしました。
これで試して見ます。
ありがとうございました。
>...コントロール配列として追加したコントロールのイベントを取得...
コントロールの配列は使用できないのだから、オブジェクトの配列を使うのだ。
Dim arrayStr() As String = {"赤", "青", "黄"}
Dim tb() As Object = {TextBox1, TextBox2, TextBox3}
For i As Integer = 0 To 2
tb(i).Text = arrayStr(i)
Next
コントロールの場合は配列ではなく、コレクションを使うのだ。
Dim ct As Control
Dim arrayStr() As String = {"赤", "青", "黄"}
For Each ct In Controls
For i As Integer = 1 To Controls.Count
If ct.Name = "TextBox" + CStr(i) Then
ct.Text = arrayStr(i - 1)
End If
Next
Next
さるべーじさんは
>dim arrayStr() String = {"赤", "青", "黄"}
>TextBox & i & .Text = arrayStr(i-1)
この文法がおかしと言ってますよ。確かに。。。。。(^^;
コードを直打ちでなくデバッグしてから貼り付けた方がいいかな。
よく考えたらこんなことしてる暇は無いんだ。汗;
とりあえず、どんな方法で解決したのか、具体的に報告して頂けるとありがたいと思います。
コントロール "の" 配列の作成とイベント ハンドラの設定
http://jeanne.wankuma.com/tips/control/02-arraycontrol.html
[参考]
隣りの『Visual Basic 初心者掲示板』の過去ログ検索『コントロール配列』でも
引っ掛かるスレッド。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200505/05050073.txt
昨夜はネットで検索した情報では理解できず
Dim testTextBox(30) As System.Windows.Forms.TextBox
For i As Integer = 0 To 30
testTextBox(i) = New TextBox
With testTextBox(i)
Select Case i
Case 0
.Text = "あいう"
AddHandler testTextBox(i).TextChanged, AddressOf ....
'すべて書いて逃げました(^_^;
End Select
.Font =
.Width =
.Height =
.Location =
End With
Me.Controls.Add(testTextBox(i))
Next
今夜 じゃんぬねっと さんのリンク先のコードと
ねろ さんのコードを参考に書きなおしてみます。
VB.NETは良く分からないけどVB6みたいに
Dim i as Long
For i = 1 to 3
Controls("TextBox" & CStr(i)).Text = CStr(i)
Next
みたいに書いてはダメなの?
他言語への移植があるならダメそうだけど……
>GOD さん
ControlCollection クラスの Item インデクサは int のみだと思います。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfSystemWindowsFormsControlControlCollectionClassItemTopic.asp
最初の質問が
>TextBox1、TextBox2、TextBox3 のコントロールがあります。
ということなので、動的な配列は無いと思いましたが。
白虎さんのそれはそれで殆ど出来ているのでは。
Dim testTextBox(30) As System.Windows.Forms.TextBox
For i As Integer = 0 To 30
testTextBox(i) = New TextBox
With testTextBox(i)
.Text = "あいう" + CStr(i)
AddHandler .TextChanged, AddressOf TextBox_TextChanged
.Width = 50
.Left = (i Mod 10) * testTextBox(i).Width
.Top = (i \ 10) * testTextBox(i).Height
.Tag = i '識別は一応タグで
End With
Me.Controls.Add(testTextBox(i))
Next
Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim MyTextBox = DirectCast(sender, TextBox)
End Sub
>じゃんぬねっと さん
>ControlCollection クラスの Item インデクサは int のみだと思います。
>
私の使っている環境がVB2005β1だから使えるんですかね?
Controls, Item共にインテリセンス表示時に第二候補として
Item(Key As String)
が出てきますね。
.Net〜.Net2003ではControlsの引き数としてStringは使えなくなっていて2005
で復活(予定)と言うことなんでしょうかね?(β2で使えなくなってたりして(^^;)
'--- VB2005β1では大丈夫そう ---
Dim i as Long
Dim x as Control.ControlCollection = Controls
For i = 1 to 3
'Controls("TextBox" & CStr(i)).Text = CStr(i)
x.Item("TextBox" & CStr(i)).Text = CStr(i)
Next
'--- ここまで ---
はい、VB2005 からは使えます。
VB6 ユーザのためにかなりの互換性が重視されていますので。
# それが良いか悪いかはかなりの論議がありますけど。
いままでリフレクション使った関数使ってました
Public Shared Function FindControl2(ByVal parentCtl As Control, ByVal ctlName As String) As Control
Dim myPropertyInfo As System.Reflection.PropertyInfo
Dim myObject As Object
myPropertyInfo = parentCtl.GetType().GetProperty(ctlName , Reflection.BindingFlags.Instance _
Or Reflection.BindingFlags.NonPublic)
If Not myPropertyInfo Is Nothing Then
myObject = myPropertyInfo.GetValue(parentCtl, Nothing)
Return CType(myObject, Control)
End If
Return Nothing
End Function
どこかから頂いてきたサンプルです。
findcontrol2(me,"textbox" & i.tostring ).text="text1"
みたいにできて便利でした。
ループ内で大量に使ってるので2005の書き方とパフォーマンスどのくらい
違うのかちょっと気になります。
ありがとうございます。
書きなおして見ました。
Privat pTextBox As System.Windows.Forms.TextBox()
Private pChStr(30) As String
'pChStr(30)はXMLファイルに書き出した設定値を
'この配列に読み込んでいます。
'テキストボックス描画
pTextBox = New TextBox(30) {}
Dim fontF As New Font("MS UI Gothic", 9)
Dim x, y As Integer
For i As Integer = 0 To 30
pegTextBox(i) = New TextBox
pegTextBox(i).Name = "pTextBox" & (i + 1).ToString()
pegTextBox(i).Font = fontF
pegTextBox(i).Text = pChStr(i)
pegTextBox(i).Width = 150
pegTextBox(i).Height = 23
x = 50
y = 20 + (i * 28)
pTextBox(i).Location = New Point(x, y)
Me.Controls.Add(pTextBox(i))
AddHandler pTextBox(i).TextChanged, AddressOf PTextBoxes_TextChanged
Next
Private Sub PTextBoxes_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim hTextBox As TextBox = DirectCast(sender, TextBox)
If hTextBox.Name = "pTextBox1" Then
pdChStr(0) = CType(sender, TextBox).Text
End If
'ここはすべて書きました。
End Sub
これでもコンパイルできました。
イベントを拾うのにIF文を31個書きました。
ん〜!このコードではコンパイルは通りません。(^^;
元のコードをコピペした後に修正をしましたね。
>イベントを拾うのにIF文を31個書きました。
If文では無くてこのような場合は、Select Case文なのでは。
まあそれはそれとして、PTextBoxes_TextChangedの引数senderには、イベント発生元の
オブジェクトが渡されて来ますから、ちょっと工夫して、送り先の pTextBoxのTagに
配列のインデックス番号を仕込んで置きます。(名前に仕込んであるのでそれを使う手もある。)
こうすると hTextBox.Tagで配列のインデックス番号が取得出来、TextBoxをオブジェクトの
配列にし、共通のイベントハンドラーを使う効果が出ます。
ざざっと直すと、こんな感じ、もちろん細かいところは見てません。
Private pTextBox(30) As System.Windows.Forms.TextBox
Private pChStr(30) As String
Dim fontF As New Font("MS UI Gothic", 9)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i As Integer = 0 To 30
pTextBox(i) = New TextBox
With pTextBox(i)
.Name = "pTextBox" & (i + 1).ToString()
.Font = fontF
.Text = pChStr(i)
.Width = 150
.Height = 23
.Tag = i 'タグで配列のインデックスを取得
.Left = 50
.Top = 20 + (i * 28)
AddHandler .TextChanged, AddressOf PTextBoxes_TextChanged
End With
Me.Controls.Add(pTextBox(i))
Next
End Sub
Private Sub PTextBoxes_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim hTextBox As TextBox = DirectCast(sender, TextBox)
pChStr(hTextBox.Tag) = pTextBox(hTextBox.Tag).Text
End Sub
ねろ さん はい修正しました。
稚拙な書き方で複雑にしてしまっているので
簡素化したほうが良いかと(^_^;
もうひとつの コントロール ラベル にはWithをつかいましたが
このテキストボックスにはWithはつかわなかったです。
テキストボックス の Tag を使ったほうがスマートですね
変更します。
ありがとうございました。
修正、レイトバインドになってました。m(__)m
△ pChStr(hTextBox.Tag) = pTextBox(hTextBox.Tag).Text
○ pChStr(CInt(hTextBox.Tag)) = pTextBox(CInt(hTextBox.Tag)).Text
Indexをタグに設定せずに、名前からを抽出するには、
Dim Index As Integer
Index = CInt(hTextBox.Name.Substring(Len("pTextBox"), Len(hTextBox.Name) - Len("pTextBox"))) - 1
又はちょっとトリッキーですが、
Index = CInt(hTextBox.Name.Replace("pTextBox", "")) - 1
等で出来ます。
.NET Framework 的には、こうかな。
Public Class ControlArray
Public Shared Function GetIndex(ByVal sender As Object) As Integer
Dim hControl As Control = DirectCast(sender, Control)
If Not hControl Is Nothing Then
Dim nIndex As String = String.Empty
Dim nName As String = hControl.Name
For i As Integer = hControl.Name.Length - 1 To 0 Step -1
If Char.IsDigit(nName.Chars(i)) Then
nIndex = nName.Chars(i) & nIndex
Else
Exit For
End If
Next i
If nIndex <> String.Empty Then
Return Int32.Parse(nIndex)
End If
End If
End Function
End Class
>>じゃんぬねっとさん なるほど。
実際は、やはり正攻法でIndexはどこのも埋め込まず
Private Sub PTextBoxes_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim hTextBox As TextBox = DirectCast(sender, TextBox)
MsgBox(GetIndex(sender, pTextBox).ToString)
End Sub
Private Function GetIndex(ByVal sender As Object, ByVal obj() As Object) As Integer
For i As Integer = LBound(obj) To UBound(obj)
If sender Is obj(i) Then
Return i
Exit For
End If
Next
End Function
こんなことをやるんでしょうか。
ちなみに、私の場合はカスタムコントロールに Index プロパティを設けやっております。
# 蛇足:
# VB2002 移行は添え字は 0 からスタート、また配列は Length プロパティから取得します。
# VB なまりのない、.NET Framework なコーディングをすると以下のような感じでしょうか?
Private Function GetIndex(ByVal sender As Object, ByVal obj As Object()) As Integer
For i As Integer = 0 To obj.Length - 1
If sender Is obj(i) Then
Return i
End If
Next i
'/ 失敗時の対策
Return -1
End Function