
Originally Posted by
rjv_rnjn
@jmcilhinney, does that mean we can define a event handler accepting three arguments?
As I said, the signature of the event handler must match the signature of the event. If you've declared the event yourself then you can make the signature anything you want.
Having said that, I very, VERY strongly suggest that you follow the convention and declare EVERY event with two arguments only: the first ALWAYS an Object named "sender" and the second ALWAYS an EventArgs (or a type that inherits EventArgs) named "e". If you want to pass data to the event handler then you should be deriving, either directly or indirectly, your own type from EventArgs and passing an instance of that to the second argument. The following is VB code but gives you the idea of what I'm talking about. Here's my custom EventArgs type:
VB Code:
''' <summary>
''' Provides data for an event raised to indicate that a text value is changing.
''' </summary>
''' <remarks>
''' Provides an opportunity to cancel the change if the new value is not appropriate.
''' </remarks>
Public Class StringChangeCancelEventArgs
Inherits System.ComponentModel.CancelEventArgs
#Region " Variables "
''' <summary>
''' The current value of the text.
''' </summary>
Private _currentValue As String
''' <summary>
''' The new value of the text.
''' </summary>
Private _proposedValue As String
#End Region 'Variables
#Region " Properties "
''' <summary>
''' Gets the current value of the text.
''' </summary>
''' <value>
''' A <b>String</b> containing the current value of the text.
''' </value>
Public ReadOnly Property CurrentValue() As String
Get
Return _currentValue
End Get
End Property
''' <summary>
''' Gets the new value of the text.
''' </summary>
''' <value>
''' A <b>String</b> containing the new value of the text.
''' </value>
Public ReadOnly Property ProposedValue() As String
Get
Return _proposedValue
End Get
End Property
#End Region 'Properties
#Region " Constructors "
''' <summary>
''' Initialises a new instance of the <see cref="StringChangeCancelEventArgs"/> class.
''' </summary>
''' <param name="proposedValue">
''' The value the text will have after the change.
''' </param>
''' <param name="currentValue">
''' The current value of the text.
''' </param>
Public Sub New(ByVal proposedValue As String, ByVal currentValue As String)
Me._proposedValue = proposedValue
Me._currentValue = currentValue
End Sub
#End Region 'Constructors
End Class
and here's my event that uses it:
VB Code:
''' <summary>
''' Occurs when the <see cref="Name"/> property value is changing.
''' </summary>
''' <remarks>
''' Provides an opportunity to cancel a name change if the proposed name is already in use.
''' </remarks>
Public Event NameChanging As EventHandler(Of StringChangeCancelEventArgs)
Here's the method that raises the event:
VB Code:
''' <summary>
''' Raises the <see cref="NameChanging"/> event.
''' </summary>
''' <param name="e">
''' A <see cref="StringChangeCancelEventArgs"/> object containing the data for the event.
''' </param>
Protected Overridable Sub OnNameChanging(ByVal e As StringChangeCancelEventArgs)
RaiseEvent NameChanging(Me, e)
End Sub
and here's the property that calls that method:
VB Code:
''' <summary>
''' Gets or sets the name of the button layout.
''' </summary>
''' <value>
''' A <b>String</b> containing the name of the button layout.
''' </value>
Public Property Name() As String
Get
Return Me._name
End Get
Set(ByVal value As String)
If Me._name <> value Then
Dim e As New StringChangeCancelEventArgs(value, Me._name)
Me.OnNameChanging(e)
'Update the value if and only if the new value is different and the change is not cancelled.
If Not e.Cancel Then
Me._name = value
Me.OnNameChanged(EventArgs.Empty)
End If
End If
End Set
End Property
Now when the NameChanging event is raised the event handlers receive a StringChangeCancelEventArgs object. Here's how I use that object:
VB Code:
''' <summary>
''' Handles the <see cref="ButtonLayout.NameChanging">NameChanging</see> event for all items in the collection.
''' </summary>
Private Sub ButtonLayout_NameChanging(ByVal sender As Object, ByVal e As StringChangeCancelEventArgs)
Dim item As ButtonLayout = TryCast(sender, ButtonLayout)
If item IsNot Nothing Then
Dim name As String = e.ProposedValue
'Cancel the change if an existing item already has the proposed name.
If Me.IndexOfName(name) <> -1 Then
e.Cancel = True
Me.OnDuplicateNameRejected(New DuplicateNameRejectedEventArgs(name))
End If
End If
End Sub