Search code examples
vb.netimagevisual-studio-2010pictureboxhandles

How Can I Put An Array Into The Handles In A Form For VB.NET?


i am developing a program, which allows you to select seats to reserve in a concert hall by clicking/rolling over a set of pictureboxes, which looks like this like this:

http://postimg.org/image/urhvij3xn/

I know how to make all of these images have roll over effect , but only individually, not as an array.

The closest to a solution i have that allows me to use the same code for all of my pictureboxes is:

 Private Sub ClickImage(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox100.MouseClick, PictureBox101.MouseClick, PictureBox102.MouseClick

But this requires me to enter every single picturebox into the handles area. Is there any way that I can enter an array of pictureboxes into the handles and then use the sender command to detect which one?

Thanks


Solution

  • The handles syntax is at once a handy feature of VB.NET but also can be a crutch. For simple applications it works ok but, as you have discovered, it is not the most elegant approach for larger projects.

    There are a few approaches you could use. What I have suggested in comments is an approach that can be a bit of a hack if you have already worked yourself into a corner. If you're not so far along that you can start with a better approach, then ideally you would be creating your PictureBoxes programmatically rather than dragging and dropping them onto your form at design time. The habit of developing like this tends to create huge messes of code in your application that are difficult to manage. Consider first making a class like :

    Private Class ConcertSeat
        Inherits PictureBox
        Private _row As Integer
        Private _column As Integer
    
        Public Property Row As Integer
            Get
                Return _row
            End Get
            Set(value As Integer)
                _row = value
            End Set
        End Property
        Public Property Column As Integer
            Get
                Return _column
            End Get
            Set(value As Integer)
                _column = value
            End Set
        End Property
    
        Protected Overrides Sub OnMouseEnter(e As System.EventArgs)
            MyBase.OnMouseEnter(e)
            ' do rollover
        End Sub
        Protected Overrides Sub OnMouseLeave(e As System.EventArgs)
            MyBase.OnMouseLeave(e)
            ' etc
        End Sub
    End Class
    

    This is obviously just a skeleton class - you should get the idea. In the class above you would probably want to load and associate the images for the rollovers, etc. Any custom behaviour that will be common to all of the components. If you are incorporating images into your control above you would obviously also want to implement IDisposable to ensure that you clean up the images when the control is disposed.

    You can also add properties to identify IsBooked, for example, and even an ID or cross-reference number to link to the person who has booked the seat, etc. The design will have to be up to you - you know the needs better than we do.

    Then on your form, without needing to drag and drop anything, simply

    Private SeatList As New List(Of ConcertSeat)
    
    Private Sub Form1_Load(sender As Object, e As EventArgs) _
                                                   Handles MyBase.Load
        Dim I As Integer
        Dim j As Integer
        Dim newSeat As ConcertSeat
        For I = 0 To 10
            For j = 0 To 10
                newSeat = New ConcertSeat
                newSeat.Row = I
                newSeat.Column = j
                ' AddHandler here does the same job as the Handles clause **!**
                AddHandler newSeat.Click, AddressOf ClickImage
                SeatList.Add(newSeat)
                ' Add Control To Form
                ' Assume here that you have added properties 
                ' to the class that define the xDimension and 
                ' yDimension of the image so that they are laid
                ' out in a grid on your form. 
                newSeat.Top = 10 + newSeat.yDimension * I
                newSeat.Right = 10 + newSeat.xDimension * j
                Me.Controls.Add(newSeat)
            Next
        Next
    End Sub
    

    This is a really rough idea, and a somewhat specific one, but it should outline the type of approach that will make your life a lot easier. You don't even have to have the seat inherit from PictureBox - you could keep them separate as a class for data and a class for the image, linked via a Dictionary or something similar.

    Also don't forget to unhook the handlers when the form is destroyed :

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) _
                                                    Handles MyBase.FormClosing
        For Each seat In SeatList
            RemoveHandler seat.Click, AddressOf ClickImage
        Next
    End Sub
    

    Forgetting to unhook handlers can pin objects in memory and prevent the garbage collector from cleaning them up (creating memory leaks).