こんなことできないでしょうか?

解決


白虎  2005-06-13 17:13:49  No: 90418  IP: [192.*.*.*]

VB.NETです。
TextBox1、TextBox2、TextBox3  のコントロールがあります。
これに
dim arrayStr() String = {"赤", "青", "黄"} 
For i as Integer = 1 To 3
  TextBox & i & .Text = arrayStr(i-1)
Next

よろしくお願いします。

編集 削除
さるべーじ  2005-06-13 18:34:10  No: 90419  IP: [192.*.*.*]

文法的に間違っているコードを見せてただ「こんなこと」と言われても、
何をしたいのかを汲み取ることは非常にむずかしいと思います。

まずは文章できちんと「何をしたいか」を説明し、
その上で「こういうコードを書きましたが、
予想に反してXXになってしまいます」などと
書いたほうが、希望と問題点がはっきりしますよね。

編集 削除
クラゲ  URL  2005-06-13 19:35:52  No: 90420  IP: [192.*.*.*]

やりたいことは、


コントロール配列を本当は使いたいですってことね。
VB6までは、確かに簡単にできましたが、
.NETからは、コントロール配列は利用できません。

ただし、方法はあります。
まずは、Googleで探してみてください。
誰かが同じことをしようとしているはずです。

編集 削除
白虎  2005-06-13 20:01:55  No: 90421  IP: [192.*.*.*]

すんませんでした。
どういうふうな言葉にしたらいいのか解らず
こう書いたほうが解りやすいかと勘違していました。

TextBox1.Text =  "あいう"
の  TextBox1  の数字「1」をネクスト文の中で
連続して代入できないかなと思ったのです
TextBox1  TextBox2  TextBox3  TextBox4  の
テキストプロパティにすべて  同じ言葉を入れたいのです。

検索のキーワード「コントロール配列」で調べて見ます。

編集 削除
白虎  2005-06-13 21:01:01  No: 90422  IP: [192.*.*.*]

調べて見ました。
コレクション変数  とか  コントロール配列として追加したコントロールのイベントを取得  など
いろいろヒットしました。
これで試して見ます。
ありがとうございました。

編集 削除
ねろ  2005-06-13 21:31:40  No: 90423  IP: [192.*.*.*]

>...コントロール配列として追加したコントロールのイベントを取得...
コントロールの配列は使用できないのだから、オブジェクトの配列を使うのだ。
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)
この文法がおかしと言ってますよ。確かに。。。。。(^^;
コードを直打ちでなくデバッグしてから貼り付けた方がいいかな。
よく考えたらこんなことしてる暇は無いんだ。汗;

編集 削除
じゃんぬねっと  URL  2005-06-14 09:22:27  No: 90424  IP: [192.*.*.*]

とりあえず、どんな方法で解決したのか、具体的に報告して頂けるとありがたいと思います。

コントロール "の" 配列の作成とイベント ハンドラの設定
http://jeanne.wankuma.com/tips/control/02-arraycontrol.html

編集 削除
特攻隊長まるるう  2005-06-14 10:21:35  No: 90425  IP: [192.*.*.*]

[参考]
隣りの『Visual Basic 初心者掲示板』の過去ログ検索『コントロール配列』でも
引っ掛かるスレッド。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200505/05050073.txt

編集 削除
白虎  2005-06-14 10:47:07  No: 90426  IP: [192.*.*.*]

昨夜はネットで検索した情報では理解できず

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

今夜  じゃんぬねっと  さんのリンク先のコードと
ねろ  さんのコードを参考に書きなおしてみます。

編集 削除
GOD  2005-06-14 11:40:49  No: 90427  IP: [192.*.*.*]

VB.NETは良く分からないけどVB6みたいに
    Dim i as Long

    For i = 1 to 3
        Controls("TextBox" & CStr(i)).Text = CStr(i)
    Next
みたいに書いてはダメなの?
他言語への移植があるならダメそうだけど……

編集 削除
じゃんぬねっと  URL  2005-06-14 11:59:14  No: 90428  IP: [192.*.*.*]

>GOD さん
ControlCollection クラスの Item インデクサは int のみだと思います。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfSystemWindowsFormsControlControlCollectionClassItemTopic.asp

編集 削除
ねろ  2005-06-14 12:54:42  No: 90429  IP: [192.*.*.*]

最初の質問が
>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

編集 削除
GOD  2005-06-14 14:18:47  No: 90430  IP: [192.*.*.*]

>じゃんぬねっと さん
>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
'--- ここまで ---

編集 削除
じゃんぬねっと  URL  2005-06-14 14:26:10  No: 90431  IP: [192.*.*.*]

はい、VB2005 からは使えます。
VB6 ユーザのためにかなりの互換性が重視されていますので。

# それが良いか悪いかはかなりの論議がありますけど。

編集 削除
medaka  2005-06-14 14:57:47  No: 90432  IP: [192.*.*.*]

いままでリフレクション使った関数使ってました

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の書き方とパフォーマンスどのくらい
違うのかちょっと気になります。

編集 削除
白虎  2005-06-14 22:25:26  No: 90433  IP: [192.*.*.*]

ありがとうございます。
書きなおして見ました。

 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個書きました。

編集 削除
ねろ  2005-06-15 08:41:04  No: 90434  IP: [192.*.*.*]

ん〜!このコードではコンパイルは通りません。(^^;
元のコードをコピペした後に修正をしましたね。

>イベントを拾うのに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

編集 削除
白虎  2005-06-15 10:16:59  No: 90435  IP: [192.*.*.*]

ねろ  さん  はい修正しました。
稚拙な書き方で複雑にしてしまっているので
簡素化したほうが良いかと(^_^;
もうひとつの  コントロール  ラベル  にはWithをつかいましたが
このテキストボックスにはWithはつかわなかったです。

テキストボックス  の  Tag  を使ったほうがスマートですね
変更します。
ありがとうございました。

編集 削除
ねろ  2005-06-15 11:15:59  No: 90436  IP: [192.*.*.*]

修正、レイトバインドになってました。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
等で出来ます。

編集 削除
じゃんぬねっと  URL  2005-06-15 12:02:02  No: 90437  IP: [192.*.*.*]

.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

編集 削除
ねろ  2005-06-15 17:16:35  No: 90438  IP: [192.*.*.*]

>>じゃんぬねっとさん  なるほど。

実際は、やはり正攻法で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
こんなことをやるんでしょうか。

編集 削除
じゃんぬねっと  URL  2005-06-15 21:20:20  No: 90439  IP: [192.*.*.*]

ちなみに、私の場合はカスタムコントロールに 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

編集 削除