こんにちわ。
VB.NETで開発をしているのですが、
どなたかやり方を知っていたら教えていただけないでしょうか?
こんなことがやりたいのですが、
AddHandler button1.click, AddressOf button1_click
AddHandler button2.click, AddressOf button2_click
AddHandler button3.click, AddressOf button3_click
AddHandler button4.click, AddressOf button4_click
このままだと、あまりかっこよくないので、以下のように出来たら
うれしいのですが、これを実現する方法って何かあるのでしょうか?
Dim controlArray() As string = {button1, button2, button3, button4}
Dim myObj As object
Dim myObjName As String
For Each myObjName In controlArray
For Each myObj In Me
if myObj.Name = myObjName then
AddHandler myObj.click, AddressOf myObjName & "_click" ' ← こんなことはできないけど、何か方法があればうれしいっす。
endif
next
next
つまり、AddressOfで指定する関数名を、文字列で指定したいのです。
どなたかご助言お願いいたします。
> このままだと、あまりかっこよくないので、
そうですか? 文字列指定だと、コンパイル時にチェックができないので、
むしろかっこ悪い気もしますが……まぁ、個人の主観にもよりますしね。(^^;
> AddHandler button1.click, AddressOf button1_click
こちらでは、「button1」は System.Windows.Forms.Button 型なのに、
> Dim controlArray() As string = {button1, button2, button3, button4}
こちらでは、「button1」が String 型であるかのように見えますが、記述ミスでしょうか?
> つまり、AddressOfで指定する関数名を、文字列で指定したいのです。
たとえば、こんな感じで書く事ができます。
'下記4メソッドは、意図的に Handles 句をつけずに宣言してあります。
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Click1")
End Sub
Private Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Click2")
End Sub
Private Sub Button3_Click(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Click3")
End Sub
Private Sub Button4_Click(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Click4")
End Sub
'チェックボックスのon/offで、イベントハンドラの関連付けを登録/解除します。
Private Sub CheckBox1_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) Handles CheckBox1.CheckedChanged
Dim Buttons() As Button = {Button1, Button2, Button3, Button4}
Dim UseEvent As Boolean = CheckBox1.Checked
Dim BF As BindingFlags 'メソッドの検索条件
BF = BF Or BindingFlags.DeclaredOnly '継承元のメンバを含めない
BF = BF Or BindingFlags.NonPublic '非Publicメソッドを含める
BF = BF Or BindingFlags.Instance 'インスタンスメソッドを含める
'今回は、下記の条件は含めない
'BF = BF Or BindingFlags.Public 'Publicメソッドを含める
'BF = BF Or BindingFlags.Static 'Sharedメソッドを含める
Dim Methods() As MethodInfo = Me.GetType().GetMethods(BF)
For Each M As MethodInfo In Methods
Dim MethodName As String = M.Name
For Each B As Button In Buttons
If StrComp(MethodName, B.Name & "_Click", CompareMethod.Text) = 0 Then
Dim D As [Delegate]
D = [Delegate].CreateDelegate(GetType(EventHandler), Me, MethodName)
If UseEvent Then
AddHandler B.Click, DirectCast(D, EventHandler)
Trace.WriteLine("AddHandler:" & MethodName)
Else
RemoveHandler B.Click, DirectCast(D, EventHandler)
Trace.WriteLine("RemoveHandler:" & MethodName)
End If
Exit For
End If
Next
Next
End Sub
少し補足。上記から、コアとなる部分だけ取り出すと、下記の3行だけで書けます。
For Each B As Button In New Button() {Button1, Button2, Button3, Button4}
AddHandler B.Click, DirectCast([Delegate].CreateDelegate(GetType(EventHandler), Me, B.Name & "_Click"), EventHandler)
Next
先の例でリフレクションが使われているのは、Sub Button1_Click などが
定義されているか、その存在チェックを行っているためです。
(厳密に行うなら、メソッド引数のチェックなども必要ですけれどね)
魔界の仮面弁士さん。
ありがとうございます。
教えていただいた方法で、無事、実現できました。
ツイート | ![]() |