JDGiants JDGiants - 2 months ago 8
Vb.net Question

Beginner ? - event handling for multiple custom controls

Working on a Windows Forms app for employee scheduling. I have a main form with several FlowPanels, each populated with several instances of a custom control. Each custom control can raise a LMB-clicked and a RMB-clicked event. Currently, the controls in the flowpanels are in an 2-dimension array.

How do I identify which custom control was clicked?

I've looked at other threads on SO (that I can't figure out how to refer to here, but AddressOf with parameter).

Until I teach myself the use of lambdas (which I couldn't get to work, btw, but was the only potential solution I could find), would there be other ways to solve this?

FWIW, I can recode the custom control, if necessary.

EDIT:
This is the code for the custom control:

`Public Class ShiftViewControl
Inherits UserControl

'Sub-class clsShiftViewData
Public Class ClsShiftViewData
'clsShiftViewData private properties
Private _employee As String = ""
Private _job As String = ""
Private _startDate As Date = New Date(1900, 1, 1, 0, 0, 0, 0)
Private _endDate As Date = New Date(1900, 1, 1, 0, 0, 0, 0)
Private _hours As Double = 0
Private _request As Boolean = False
Private _splitShift As Boolean = False
Private _override As Boolean = False
Private _notes As String = ""

'clsShiftViewData class property statements
Public Property Employee() As String
Get
Return _employee
End Get
Set(ByVal value As String)
_employee = value
End Set
End Property
Public Property Job() As String
Get
Return _job
End Get
Set(ByVal value As String)
_job = value
End Set
End Property
Public Property StartDate() As Date
Get
Return _startDate
End Get
Set(ByVal value As Date)
_startDate = value
End Set
End Property
Public Property EndDate() As Date
Get
Return _endDate
End Get
Set(ByVal value As Date)
_endDate = value
End Set
End Property
Public Property Hours() As Double
Get
Return _hours
End Get
Set(value As Double)
_hours = value
End Set
End Property
Public Property Request() As Boolean
Get
Return _request
End Get
Set(ByVal value As Boolean)
_request = value
End Set
End Property
Public Property SplitShift() As Boolean
Get
Return _splitShift
End Get
Set(ByVal value As Boolean)
_splitShift = value
End Set
End Property
Public Property Override() As Boolean
Get
Return _override
End Get
Set(ByVal value As Boolean)
_override = value
End Set
End Property
Public Property Notes() As String
Get
Return _notes
End Get
Set(ByVal value As String)
_notes = value
End Set
End Property
End Class

Public Event LmbClicked(ByRef sender As Object, ByVal e As MouseEventArgs)
Public Event RmbClicked(ByRef sender As Object, ByVal e As MouseEventArgs)

Private _shiftViewData As New ClsShiftViewData

Private Sub HandleAllClicks(ByVal sender As Object, ByVal e As MouseEventArgs) Handles lblEmployee.MouseClick, lblJob.MouseClick, lblStartTime.MouseClick, _
lblEndTime.MouseClick, lblHours.MouseClick, _
lblRequest.MouseClick, lblNotes.MouseClick, Me.MouseClick, _
lblSplitShift.MouseClick, lblOverride.MouseClick
If e.Button = Windows.Forms.MouseButtons.Right Then
RaiseEvent RmbClicked(Me, e)
Else
RaiseEvent LmbClicked(Me, e)
End If
End Sub



'MISC methods here

Public Sub PutData(ByVal svInfo As ClsShiftViewData)
'Fill both _shiftViewData and corresponding form controls
_shiftViewData = svInfo
With _shiftViewData
lblEmployee.Text = .Employee
lblJob.Text = .Job
lblStartTime.Text = .StartDate.ToShortTimeString
lblEndTime.Text = .EndDate
'...
lblNotes.Text = .Notes
End With

End Sub
Public Sub GetData(ByRef svInfo As ClsShiftViewData)
With svInfo
.Employee = _shiftViewData.Employee
.Job = _shiftViewData.Job
.StartDate = _shiftViewData.StartDate
.EndDate = _shiftViewData.EndDate
.Hours = _shiftViewData.Hours
.Request = _shiftViewData.Request
.Notes = _shiftViewData.Notes
End With

End Sub


Private Sub ShiftViewControl_Load(sender As Object, e As EventArgs) Handles MyBase.Load

End Sub


End Class

And this is the code I'm currently working on:

`Imports ShiftBox ' .dll includes custom control ShiftViewControl


'
'NOTE: A lot of this code is experimenting, FYI, and I've removed some code to clarify
'

Public Class FrmShiftBoard
Public Sv(7, 6) As ShiftViewControl 'Array will eventually be dynamic
Public WithEvents TempSvc As New ShiftViewControl

Public Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
DebugMode = False
Const rowcount As Integer = 7
Const spacing As Integer = 15
Const intSpace As Integer = 15
Dim fp(rowcount) As FlowLayoutPanel
Dim tempFillData As New ShiftBox.ShiftViewControl.ClsShiftViewData
Dim col As Integer
Dim row As Integer
Dim locationPoint As New Point
Dim newLocationPoint As New Point
Dim tempPoint As New Point


'Following section is my newbie code to setup the form
Me.Width = (TempSvc.Width * 7 + intSpace * 7)
Me.Height = (TempSvc.Height * rowcount + intSpace * 7)
locationPoint.X = 1
locationPoint.Y = TempSvc.Size.Height * row
For row = 0 To rowcount - 1
fp(row) = New FlowLayoutPanel
fp(row).AutoSize = True
tempPoint.X = TempSvc.Size.Width : tempPoint.Y = TempSvc.Size.Height
fp(row).Size = tempPoint
newLocationPoint.X = locationPoint.X
newLocationPoint.Y = locationPoint.Y + (TempSvc.Height * row) + spacing * row
fp(row).Location = newLocationPoint
Me.Controls.Add(fp(row))
Next

For row = 0 To rowcount - 1
For col = 0 To 6

'I've tried multiple variations of the following line to no avail
AddHandler Sv(row, col).LmbClicked, AddressOf myHandler

Sv(row, col).Name = "SV" + row.ToString + "," + col.ToString()
Sv(row, col).PutData(EmployeeList(col).ToShiftViewFill)
fp(row).Controls.Add(Sv(row, col))
Next
Next

End Sub


Private Sub myHandler() 'Handles ?
'Here is where I beiieve I should handle the LmbClicked event
'and determine which ShiftViewControl fired the event. Then
'I can branch to code based on which ShiftViewControl
'was selected. Maybe I should use something other than
'an array?

End Sub


End Class

And I have no clue how to get the "End Class" lines into the code samples :(

Answer

Every event handler should have the same basic signature, i.e. a sender parameter of type Object and an e parameter of type EventArgs or some derived type. The sender parameter refers to the object that raised the event. That's how you always access the object that raised the event and that's how you should determine which UC was clicked in your case.