ISCL is a Intelligent Information Consulting System. Based on our knowledgebase, using AI tools such as CHATGPT, Customers could customize the information according to their needs, So as to achieve

Using the Custom Event Keyword

2


Part One of this series builds a couple of examples where VB.NET events are coded without using Framework objects (like a Button or a TextBox). Visual Studio adds quite a bit of hidden code to implement events when you simply double-click a Framework control to add the event subroutine for it. You can do everything that Visual Studio does manually, but you have to really understand event coding to do it successfully.

A handy reference to previous articles concerning events and delegates can also be found in Part One. Since some of this article is a continuation of that one, you might want to read that first.

To Start with Part One: Events Using Your Own Code in VB.NET.

The event coding option that I'll describe here ... with some cautions ... is the use of the Custom keyword when the event is declared. The event declaration from Part One (using the delegate MatchWonHandler) looked like this:

Public Event MatchWon As MatchWonHandler
If you add the Custom keyword, Visual Studio Intellisense automatically adds a code snippet with three new code blocks as soon as you press enter at the end of the statement. According to Microsoft, "Events declared as Custom must define custom AddHandler, RemoveHandler, and RaiseEvent accessors." So now you know what to call these code blocks: they're "accessors"!

Public Custom Event MatchWon As MatchWonHandlerAddHandler(value As MatchWonHandler)End AddHandlerRemoveHandler(value As MatchWonHandler)End RemoveHandlerRaiseEvent(ww As Integer, tt As Integer)End RaiseEventEnd Event

Notice that the delegate (MatchWonHandler in this case) and the parameters for it are already entered for you! The level of control that you get with the Custom keyword really isn't necessary for most programs and in the example from Part One, it's totally useless. In a way, this is a result of the really excellent implementation of events buried in Visual Studio. I'll add the Custom keyword to the Part One example anyway just to demonstrate how the events work.

Microsoft's documentation for the Custom keyword is in two categories: inadequate and none at all. But they do list two cases where it can be useful:

-> Conserving Memory
-> Avoid Blocking

But these examples actually hide the detail about how it works because they don't explain how and why the VB code changes. This example does.

Because we have to code the custom AddHandler, RemoveHandler, and RaiseEvent accessors in our code (and the VB compiler doesn't add any hidden code for these same accessors), the WithEvents qualifier when the object that raises the event (in this case, the theMatch instance of TableTennisMatch) doesn't even have to be coded anymore.

Private WithEvents theMatch As TableTennisMatch
... becomes more simply ...

Dim theMatch As New TableTennisMatch
If you only add the Custom keyword, you will notice that the example from Part One immediately stops working. It doesn't crash; it just stops executing the event code. That's because the hidden code is not added when the keyword is there.

Just as in Part One, here's the complete code for the example. Explanations will follow.

Public Class TTMatchControlDim theMatch As New TableTennisMatchPrivate Sub Form1_Load(sender As System.Object,e As System.EventArgs) Handles MyBase.LoadDim PlayerA As String = "George"Dim PlayerB As String = "Arthur"theMatch.PlayerA = PlayerAtheMatch.PlayerB = PlayerBDim PStats = XElement.Load("..\..\PlayerStats.xml")Dim pStat =From p In PStats.Select pWhere p..Value = PlayerAlblPlayerAWins.Text = pStat..ValuepStat =From p In PStats.Select pWhere p..Value = PlayerBlblPlayerBWins.Text = pStat..ValueEnd SubPrivate Sub btnAddPointA_Click(sender As System.Object,e As System.EventArgs) Handles btnAddPointA.ClicktheMatch.UpdateScore(0)lblPlayerAScore.Text =CStr(theMatch.PlayerAScore)End SubPrivate Sub btnAddPointB_Click(sender As System.Object,e As System.EventArgs) Handles btnAddPointB.ClicktheMatch.UpdateScore(1)lblPlayerBScore.Text =CStr(theMatch.PlayerBScore)End SubEnd ClassPublic Class TableTennisMatchPublic Delegate Sub MatchWonHandler(ww As Integer,pA As String, pB As String)Property PlayerA As StringProperty PlayerB As StringProperty PlayerAScore As IntegerProperty PlayerBScore As IntegerPublic Custom Event MatchWon As MatchWonHandlerAddHandler(value As MatchWonHandler)End AddHandlerRemoveHandler(value As MatchWonHandler)End RemoveHandlerRaiseEvent(ww As Integer, pA As String, pB As String)Record_WinLoss(ww, PlayerA, PlayerB)End RaiseEventEnd EventPublic Sub UpdateScore(ByVal pNum As Integer)If pNum = 0 ThenPlayerAScore += 1ElsePlayerBScore += 1End IfIf PlayerAScore > 20 ThenIf PlayerAScore >PlayerBScore + 1 ThenRaiseEvent MatchWon(0, PlayerA, PlayerB)End IfEnd IfIf PlayerBScore > 20 ThenIf PlayerBScore >PlayerAScore + 1 ThenRaiseEvent MatchWon(1, PlayerA, PlayerB)End IfEnd IfEnd SubPublic Sub Record_WinLoss(ByVal ww As Integer,ByVal pA As String, ByVal pB As String)Dim PStats =XElement.Load("..\..\PlayerStats.xml")Dim pStatA =From p In PStats.Select pWhere p..Value = pADim pStatB =From p In PStats.Select pWhere p..Value = pBIf ww = 0 ThenpStatA..Value += 1pStatB..Value += 1TTMatchControl.lblPlayerWon.Text = pA & " Wins!"ElsepStatB..Value += 1pStatA..Value += 1TTMatchControl.lblPlayerWon.Text = pB & " Wins!"End IfPStats.Save("..\..\PlayerStats.xml")TTMatchControl.lblPlayerBWins.Text = pStatB..ValueTTMatchControl.lblPlayerAWins.Text = pStatA..ValueTTMatchControl.btnAddPointA.Enabled = FalseTTMatchControl.btnAddPointB.Enabled = FalseEnd SubEnd Class
If you read Microsoft's pages about Custom event coding (linked above), you'll see that the code for the event source (in this case, "Public Custom Event MatchWon As MatchWonHandler"; in Microsoft's example, "Public Custom Event Click As EventHandler"), you'll notice that Microsoft's example is quite a bit more complex. For example, their RaiseEvent accessor block coding is:

CType(Events("ClickEvent"), EventHandler).Invoke(sender, e)
Mine is just a direct call to the subroutine that must be called when the event is raised:

Record_WinLoss(ww, PlayerA, PlayerB)
The reason is that Microsoft's example is intended to demonstrate how a custom event can be conditionally executed to allow a common memory resource to be used; mine is only intended to duplicate the function of the easier-to-code version in Part One to illustrate how using the Custom keyword can do the same thing. In my code the event handler, Record_WinLoss, is executed all the time. In Microsoft's example, it isn't, so they have to persist the event hander in a pointer variable: ClickEvent. Then the code that variable persists has to be executed with the Invoke method and the appropriate parameters. The parameters sender and e are the default parameters when you don't create your own when you declare the delegate. Recall that in Part One, I have unique parameters. In the final version:

Public Delegate Sub MatchWonHandler(ww As Integer, tt As Integer)
The key to understanding what the Custom keyword does is that the only automatic action will be to execute the appropriate accessor block whenever a handler is added, removed, or an event is raised. It can be very instructive to simply add a diagnostic debugging statement into each accessor - something like Console.Writeline("Accessor Block AddHandler") for the first one - to see when it is executed. This leads to all of the reasons why you might want to use one. If there is some code that you only want to run when a handler is removed - for example, display a warning to the user - then you can put that code in the RemoveHandler accessor block. Microsoft's example saves the event delegates in a list and checks the list.
Source...
Subscribe to our newsletter
Sign up here to get the latest news, updates and special offers delivered directly to your inbox.
You can unsubscribe at any time

Leave A Reply

Your email address will not be published.