2017-01-01 8 views
-1

私はPictureBoxN_Clickイベントをランダムに呼び出す必要があります。どうすればvb.netでこれを行うことができますか?ランダムにイベントを呼び出す

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click 
    If ListView1.Items.Count > 0 Then 
     If IsNothing(Me.ListView1.FocusedItem) Then 
      ListView1.TopItem.Selected = True 
     End If 
     For Each file As ListViewItem In ListView1.Items 
      Dim filePath As String = file.SubItems(1).Text & "\" & file.Text 
      If file.Selected = True Then 
       Process.Start(filePath) 
      End If 
     Next 
    Else 
     Dim rndm As Integer = CInt(Math.Ceiling(Rnd() * 20)) + 1 
     Dim rndpic As String = "PictureBox" & rndm & "_Click" 
     Call rndpic(Nothing, Nothing) 
    End If 
End Sub 
+0

本当に** N **の異なるハンドラを持っていますか...各PictureBoxに1つずつありますか?または、それらのすべてのために** ONE **ハンドラを持ち、正しいソースPictureBoxを渡す必要がありますか? –

+0

はい、私は** N **別のハンドラーを持っています – TheLegend27

答えて

1

私はjmcilhinneyの答えに同意しますが、ここで最初に求めたことを行う方法があります。これは、Controls.Find()を使用して、 "名前で"目的のPictureBoxへの参照を取得する方法も示しています。 Reflectionを使用して一致するメソッド名を探し、Invoke()を呼び出しています:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    Static R As New Random 
    Dim rndm As Integer = R.Next(1, 91) ' <-- return a value between 1 and 90 inclusive (yes, 91 is correct!) 
    Dim ctlName As String = "PictureBox" & rndm.ToString 
    Dim methodName As String = ctlName & "_Click" 
    Dim flags As Reflection.BindingFlags = Reflection.BindingFlags.IgnoreCase Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic 
    Dim MI As _MethodInfo = Me.GetType.GetMethod(methodName, flags) 
    If Not IsNothing(MI) Then 
     Dim matches() As Control = Me.Controls.Find(ctlName, True) 
     If matches.Length > 0 AndAlso TypeOf matches(0) Is PictureBox Then 
      Dim pb As PictureBox = DirectCast(matches(0), PictureBox) 
      MI.Invoke(Me, New Object() {pb, New EventArgs}) 
     End If 
    End If 
End Sub 
+0

反射を利用した良い解決策かもしれない – Codexer

1

まず、イベントを呼び出していません。イベントはあなたによってではなく発生します。 PictureBoxClickイベントを発生させる唯一の簡単な方法は、マウスでクリックすることです。

あなたが話しているのは、メソッドを呼び出すことです。イベントハンドラはイベントではありません。イベントハンドラは、イベントが発生したときに自動的に実行されるメソッドです。イベントハンドラを直接呼び出すことは、実際には貧弱な方法です。

実行するコードは、PictureBoxというパラメータを持つ独自のメソッドに入れてください。その後、PictureBoxesのイベントハンドラClickからそのメソッドを呼び出すことができます。あなたがそうするならば、あなたはこの場合のどんなClickイベントについても考える必要はなく、それはどのようにすべきかです。クリックが行なわれていないからです。

PictureBoxのそれぞれについて同じことをしている場合は、すべてのPictureBoxesに対して1つのイベントハンドラのみが必要です。ランダムPictureBoxのコードを実行する場合は、Buttonをクリックし、ランダムPictureBoxを選択してメソッドに渡します。例えば。

Private rng As New Random 

Private Sub PictureBoxes_Click(sender As Object, e As EventArgs) Handles PictureBox3.Click, 
                     PictureBox2.Click, 
                     PictureBox1.Click 
    'Prcoess the PictureBox that was clicked. 
    ProcessPictureBox(DirectCast(sender, PictureBox)) 
End Sub 

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    'Process a random PictureBox. 

    Dim pictureBoxes = {PictureBox1, PictureBox2, PictureBox3} 
    Dim pictureBox = pictureBoxes(rng.Next(pictureBoxes.Length)) 

    ProcessPictureBox(pictureBox) 
End Sub 

Private Sub ProcessPictureBox(pictureBox As PictureBox) 
    'Use pictureBox here. 
End Sub 
+1

PictureBoxesの配列をハードコードするのではなく、Load()イベントでControls.Find()(再帰的なオーバーロード)を使って、その配列**を一度**構築し、それをクラスレベルで保存します。 –

+0

@Idle_Mind、私は 'Load'イベントではなく' Load'イベントハンドラを意味すると思います。 'PictureBoxes'をハードコーディングしたくなければ、' Me.Controls.OfType(Of PictureBox)() 'を呼び出す傾向がありますが、' Load'イベントハンドラーではしません。その配列は、そのクラスのレベルに存在するクラスが実際には適切でないような方法でのみ必要です。パフォーマンスの向上はほとんど測定できず、目立たないため、適切な範囲を維持することが優先されます。 – jmcilhinney

+0

イベントハンドラに関するご意見に同意します。私はあまりにも多くの***を参照してくださいそれはあなたがする必要があることを意味しない***ことができます***。 IMOはもう少し情報を追加し、イベントハンドラを直接呼び出すが、イベントハンドラを呼び出しコードに強く結合する。後でイベントハンドラを変更したい場合、そのコードを壊す可能性があり、そのコードへのすべての参照をチェックする必要があります。密接に結合されたコードは本質的にユニットに分離することがより困難であるため、テストはさらに難しくなります。イベントハンドラ***はプライベートにする必要があり、コード***の他の部分にのみ公開する必要があります。 – Codexer

関連する問題