C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: 動的なコントロールのインスタンスを生成


(過去ログ 115 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■68174 / inTopicNo.1)  動的なコントロールのインスタンスを生成
  
□投稿者/ 海犬 (1回)-(2013/09/27(Fri) 17:53:59)
海犬 さんの Web サイト

分類:[VB.NET/VB2005 以降] 

2013/09/27(Fri) 18:59:42 編集(投稿者)

いつもお世話になっています。VB2010で開発してます。

コントロールのインスタンス生成時、TextBoxの場合は、

Dim control As System.Windows.Forms.TextBox
control = New System.Windows.Forms.TextBox

と書いていますが、上記のTextbox部分を動的に変更するにはどのようにすればよいのでしょうか?
(ボタンコントロールやチェックボックスコントロールなどを動的に変更したいと思っています)

よろしくお願いいたします。

引用返信 編集キー/
■68175 / inTopicNo.2)  Re[1]: 動的なコントロールのインスタンスを生成
□投稿者/ 太郎冠者 (7回)-(2013/09/27(Fri) 20:33:31)
コントロールの生成処理をメソッドに分割するなどはどうでしょうか。

例えば、このようなメソッドを作成して

Private Function MakeControl(type As Integer) As Control
    Select Case type
        Case 0
            Return New TextBox()
        Case 1
            Return New ComboBox()
        Case 2
            Return New CheckBox()
    End Select
    Return Nothing
End Function

使う時はこんな感じで

'TextBox作成
Dim c1 As Control = MakeControl(0)
Me.Controls.Add(c1)

'ComboBox作成()
Dim c2 As Control = MakeControl(1)
Me.Controls.Add(c2)

'CheckBox作成()
Dim c3 As Control = MakeControl(2)
Me.Controls.Add(c3)

引用返信 編集キー/
■68176 / inTopicNo.3)  Re[1]: 動的なコントロールのインスタンスを生成するには
□投稿者/ 魔界の仮面弁士 (353回)-(2013/09/27(Fri) 21:54:51)
No68174 (海犬 さん) に返信
> と書いていますが、上記のTextbox部分を動的に変更するにはどのようにすればよいのでしょうか?

何のためにでしょうか?

.designer.vb 相当のコードを自動生成するためのツールと言う意味であれば、CodeDOM を使う手があります。

Imports System
Imports System.IO
Imports System.CodeDom

Public Class Form1
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim var As New CodeVariableDeclarationStatement(GetType(TextBox), "ctrl",
            New CodeObjectCreateExpression(New CodeTypeReference(GetType(TextBox))))

        Using sw As New StringWriter()
            'Dim cp As New Microsoft.CSharp.CSharpCodeProvider()
            Dim cp As New Microsoft.VisualBasic.VBCodeProvider()
            cp.GenerateCodeFromStatement(var, sw, Nothing)

            sw.Flush()
            TextBox1.Text = sw.ToString()
        End Using
    End Sub
End Class


あるいは、実行時に動的生成することが目的の場合は、変数を As Control 等で受けるようにしておき、
Activator.CreateInstance で生成するとか。


Public Class Form1
    Private x As Control

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        ComboBox1.Items.Add("System.Windows.Forms.TextBox")
        ComboBox1.Items.Add("System.Windows.Forms.Button")
        ComboBox1.Items.Add("System.Windows.Forms.CheckBox")
        ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
        ComboBox1.SelectedIndex = 0
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        If x IsNot Nothing Then
            Controls.Remove(x)
            x.Dispose()
        End If

        Dim typeName As String = CStr(ComboBox1.SelectedItem)
        Dim t As Type = GetType(Control).Assembly.GetType(typeName, True)
        x = DirectCast(Activator.CreateInstance(t), Control)

        x.Text = "Sample"
        x.Visible = True
        x.Location = New Point(30, 30)
        Controls.Add(x)
    End Sub

End Class

引用返信 編集キー/
■68177 / inTopicNo.4)  Re[2]: 動的なコントロールのインスタンスを生成するには
□投稿者/ 魔界の仮面弁士 (354回)-(2013/09/27(Fri) 22:47:56)
No68176 (魔界の仮面弁士 さん) に返信
> あるいは、実行時に動的生成することが目的の場合は、変数を As Control 等で受けるようにしておき、
> Activator.CreateInstance で生成するとか。

別案。やっていることは同じですが。


Public Class Form1
    Private x As Control

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        ComboBox1.DataSource = New Type() {GetType(TextBox), GetType(Button), GetType(CheckBox), GetType(RadioButton), GetType(Form)}
        ComboBox1.DisplayMember = "Name"
        ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
    End Sub

    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
        If x IsNot Nothing Then
            Controls.Remove(x)
            x.Dispose()
        End If

        Dim t As Type = CType(ComboBox1.SelectedItem, Type)
        x = DirectCast(t.GetConstructor(Type.EmptyTypes).Invoke(Nothing), Control)
        If TypeOf x Is Form Then DirectCast(x, Form).TopLevel = False

        x.Text = "Sample"
        x.Location = New Point(30, 30)
        Controls.Add(x)
        x.Visible = True
    End Sub
End Class

引用返信 編集キー/
■68178 / inTopicNo.5)  Re[1]: 動的なコントロールのインスタンスを生成
□投稿者/ じゃんぬねっと (20回)-(2013/09/28(Sat) 00:12:46)
動的といっても、"何を" 作るのかの情報源は指定しなきゃいけないわけで... それを文字列やら数値で表現するくらいなら、素直に「型」の方が絶対良いと思います。

生成しているところでは具象型が特定できる何らかの情報が必要。それをビルド解決できて、一意に特定でき、万人が読んでわかりやすいのは「型」そのものです。

生成された後のことをどうこう言っているわけではありません。生成されたインスタンスを System.Windows.Controls.Control で抽象的に利用することは何ら問題ありません。むしろその方が望ましいくらいです。

では動的にする意味は何でしょうか? できの悪い私の頭で必死に考えましたが、「実装依存にしたくないから」くらいしか思いつきませんでした。もしそうであれば、設定によって外部注入する、つまり DI のような仕組みの方が良いと思います。
引用返信 編集キー/
■68179 / inTopicNo.6)  Re[2]: 動的なコントロールのインスタンスを生成するには
□投稿者/ 海犬 (2回)-(2013/09/28(Sat) 00:48:37)
海犬 さんの Web サイト
No68176 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士 さん、返信いただきありがとうございます。

> ■No68174 (海犬 さん) に返信
>>と書いていますが、上記のTextbox部分を動的に変更するにはどのようにすればよいのでしょうか?
>
> 何のためにでしょうか?

→説明不足で申し訳ありませんでした。あらかじめユーザーに使用するコントロールとその個数を指定してもらい、
画面表示時にユーザーに指定されたコントロールを指定された個数分だけ縦に並べるという開発をしております。
ただその指定されるコントロールはVisualStudio標準コントロールだけでなく、
ユーザーコントロールも指定できるようにしたいため、動的に変更したいと考えました。

> Dim typeName As String = CStr(ComboBox1.SelectedItem)
> Dim t As Type = GetType(Control).Assembly.GetType(typeName, True)
> x = DirectCast(Activator.CreateInstance(t), Control)

→コントロールを文字列で指定できるとは知りませんでした。こちらの方法でうまくいきそうです。
いま開発環境が手元にないため、明日改めて結果を報告します。


太郎冠者 さんもまた返信をいただきありがとうございました。
引用返信 編集キー/
■68180 / inTopicNo.7)  Re[2]: 動的なコントロールのインスタンスを生成
□投稿者/ 海犬 (3回)-(2013/09/28(Sat) 01:01:46)
海犬 さんの Web サイト
No68178 (じゃんぬねっと さん) に返信

じゃんぬねっと さん、返信いただきありがとうございました。

> では動的にする意味は何でしょうか? できの悪い私の頭で必死に考えましたが、「実装依存にしたくないから」くらいしか思いつきませんでした。もしそうであれば、設定によって外部注入する、つまり DI のような仕組みの方が良いと思います。

→お考えさせてしまってすみませんでした。。投稿が前後してしまいましたが、魔界の仮面弁士 さんの「何のためにでしょうか?」の私の返信で、動的にしたい理由を書きました。
じゃんぬねっと さんの質問に対して正確な応えになっていますでしょうか。
引用返信 編集キー/
■68182 / inTopicNo.8)  Re[3]: 動的なコントロールのインスタンスを生成
□投稿者/ 海犬 (5回)-(2013/09/28(Sat) 13:10:41)
海犬 さんの Web サイト
本件、魔界の仮面弁士 さんの別案で解決しました。

具体的には、画面に対象コントロールを張り付け、そのコントロールの型を取得し、
それをコピーしました。
コードは以下のようにしました。
(template が画面に張り付けたコントロールです)

Dim t As Type = template.GetType
Dim x As Control = DirectCast(t.GetConstructor(Type.EmptyTypes).Invoke(Nothing), Control)


回答いただき、ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -