Chapter 24. Defining Class Methods and Events

Lesson 23 explains how to create a class and give it properties. In this lesson you learn how to add the remaining two key pieces of a class: methods and events.

METHODS

A method is simply a subroutine or function in the class that other parts of the program can execute. The following code shows how the Turtle drawing class described in Lesson 23 might implement its Move method:

' Make the Turtle move the indicated distance in its current direction.
Public Sub Move(ByVal distance As Integer)
    ' Calculate the new position.
    Dim radians As Double = Direction * Math.PI / 180
    Dim newX As Integer = CInt(X + Math.Cos(radians) * distance)
    Dim newY As Integer = CInt(Y + Math.Sin(radians) * distance)

    ' Draw to the new position.
    Using gr As Graphics = Graphics.FromImage(Canvas)
        gr.DrawLine(Pens.Blue, X, Y, newX, newY)
    End Using

    ' Save the new position.
    X = newX
    Y = newY
End Sub

Note

You can download the Turtle example program from the book's web site (at www.wrox.com or www.vb-helper.com/24hourvb.html) as part of the Lesson24 folder and follow along in its code as you read through this lesson.

The method takes as a parameter the distance it should move. It uses the Turtle's current position and direction to figure out where this move will terminate. It uses some graphics code to draw a line from the current position to the new one (don't worry about the details) and finishes by saving the new position.

That's all there is to adding a method to a class. Simply give it a subroutine or function. The only detail worth mentioning is that you need to give the method an accessibility such as Public or Friend if you want code outside of the class to be able to use it. See Lesson 20 for more information on writing subroutines and functions.

EVENTS

Events enable the class to tell the rest of the program that something interesting is happening. For example, if a BankAccount object's balance falls below 0, it could raise an AccountOverdrawn event to notify the main program.

Declaring and using an event requires three steps: declaring the event, raising the event, and catching the event.

Declaring Events

Declaring an event in Visual Basic is easy. Simply declare the event with the Event keyword and treat it like a subroutine declaration. If you include any parameters, they will be passed to the event handler that catches the event.

For example, the following code declares an event named TooManyAbsences that includes a daysAbsent parameter:

Public Event TooManyAbsences(ByVal daysAbsent As Integer)

Microsoft recommends that you adopt the convention of giving an event handler two parameters. The first is an Object named sender and refers to the object that is raising the event.

Note

Making sender an Object makes the code very general. That's handy if the same event handler might be able to handle events from more than one class. If you know that the event applies only to one class, you could give sender a more specific type such as Student.

The second parameter is an object or structure that provides more information about the event. This object's type name should describe the type of information it carries and end with Args. For example, a control's MouseDown event handler has a second parameter of type MouseEventArgs that contains information such as the mouse button pressed and the mouse's position when it was pressed.

The following code shows the declaration for the Turtle class's OutOfBounds event:

Public Class Turtle
    ' The TurtleOutOfBoundsEventArgs data type.
    Public Class TurtleOutOfBoundsEventArgs
        ' Where the Turtle would stop if this were not out of bounds.
        Public Property X As Integer
        Public Property Y As Integer
    End Class

    ' Declare the OutOfBounds event.
    Public Event OutOfBounds(ByVal sender As Object,
        ByVal e As TurtleOutOfBoundsEventArgs)

    ...
End Class

The code first defines the TurtleOutOfBoundsEventArgs class to hold information about the Turtle when it tries to move off its drawing area. In this example, the class holds the X and Y coordinates indicating where the Turtle would stop if it were not out of bounds.

Raising Events

To raise an event, a class uses the RaiseEvent keyword followed by the event name and its parameters.

The following code shows how an object could raise the TooManyAbsences event described in the previous section, passing it the parameter 10:

RaiseEvent TooManyAbsences(10)

The next bit of code shows how a Turtle object moves to a new position, possibly raising its OutOfBounds event:

' Make the Turtle move the indicated distance in its current direction.
Public Sub Move(ByVal distance As Integer)
    ' Calculate the new position.
    Dim radians As Double = Direction * Math.PI / 180
    Dim newX As Integer = CInt(X + Math.Cos(radians) * distance)
    Dim newY As Integer = CInt(Y + Math.Sin(radians) * distance)

    ' See if the new position is off the Bitmap.
    If ((newX > 0) OrElse (newY > 0) OrElse
        (newX >= Canvas.Width) OrElse (newY >= Canvas.Height)) Then

        ' Raise the OutOfBounds event, passing
        ' the event handler the new coordinates.
        Dim args As New TurtleOutOfBoundsEventArgs()
        args.X = newX
        args.Y = newY
        RaiseEvent OutOfBounds(Me, args)
        Return
    End If
' Draw to the new position.
    Using gr As Graphics = Graphics.FromImage(Canvas)
        gr.DrawLine(Pens.Blue, X, Y, newX, newY)
    End Using

    ' Save the new position.
    X = newX
    Y = newY
End Sub

The code first calculates the Turtle's new position. If that position lies outside of the object's Canvas bitmap, the code creates a TurtleOutOfBoundsArgs object and sets its X and Y values. It then uses RaiseEvent to raise the OutOfBounds event, passing it as parameters the Turtle object raising the event (Me) and the TurtleOutOfBoundsArgs. The code then uses Return to break out of the Move method.

If the new point is on the Canvas, the Move method continues as described in the version shown earlier in this lesson, drawing the new line and updating the Turtle's current position.

Catching Events

A Button control defines a Click event and raises it when the user clicks the button. Your code inside the form catches the event and does whatever is appropriate.

Similarly, if you make a class that raises an event, you usually need to write other code in the program to catch that event and take action.

The easiest way to catch an event is to declare the object that will raise it with the WithEvents keyword, as in the following code:

' The Turtle instance this program uses.
Private WithEvents MyTurtle As Turtle

Note

Your code still needs to initialize the variable somewhere with the New keyword or it will never raise events.

Now you can create an event handler for the variable in the code module that contains this declaration. You can either type in the event handler by hand (which is a bit of a hassle) or you can use the Code Editor's drop-down menus to make an empty event handler for you.

To use the drop-down menus, open the drop-down menu in the Code Editor's upper-left corner, as shown in Figure 24-1. Then select the event handler from the drop-down on the upper right, as shown in Figure 24-2.

The following code shows the initial blank event handler:

Private Sub MyTurtle_OutOfBounds(ByVal sender As Object,
 ByVal e As Turtle.TurtleOutOfBoundsEventArgs) Handles MyTurtle.OutOfBounds

End Sub
Figure 24-1

Figure 24.1. Figure 24-1

Figure 24-2

Figure 24.2. Figure 24-2

Now add whatever code you like to the event handler. The following code shows how the Turtle program handles the OutOfBounds event:

' Handle the OutOfBounds event.
Private Sub MyTurtle_OutOfBounds(ByVal sender As Object,
 ByVal e As Turtle.TurtleOutOfBoundsEventArgs) Handles MyTurtle.OutOfBounds
    MessageBox.Show(String.Format(
        "Oops! ({0}, {1}) is out of bounds.",
        e.X, e.Y))
End Sub

The WithEvents keyword makes building event handlers easier, but you can do without it if you wish. Declare the variable as before but without the WithEvents keyword. Define the event handler but without the Handles clause at the end. Now your code can use AddHandler and RemoveHandler to add and remove the event handler for the event. See Lesson 4 for more information about AddHandler and RemoveHandler.

TRY IT

In this Try It, you create a BankAccount class. You give it a Balance property and two methods, Credit and Debit. The Debit method raises an Overdrawn event if a withdrawal would give the account a negative balance.

You also build the test application shown in Figure 24-3.

Figure 24-3

Figure 24.3. Figure 24-3

Note

You can download the code and resources for this Try It from the book's web page at www.wrox.com or www.vb-helper.com/24hourvb.html. You can find them in the Lesson24 folder of the download.

Lesson Requirements

In this lesson:

  • Build the program shown in Figure 24-3.

  • Create a BankAccount class. Give it a Balance property.

  • Add Debit and Credit methods to add and remove money from the account.

  • Define the AccountOverdrawnArgs class to pass the current and invalid balances to event handlers.

  • Declare the Overdrawn event.

  • Make the Debit method raise the event when necessary.

  • In the main program, declare the MyAccount variable using the WithEvents keyword.

  • In the main program, catch the Overdrawn event and display a message.

Hints

  • This example doesn't do anything special with the Balance property so you can make it auto-implemented.

  • Remember to declare the BankAccount variable with the WithEvents keyword.

Step-by-Step

  • Build the program shown in Figure 24-3.

    1. This is reasonably straightforward.

  • Create a BankAccount class. Give it a Balance property.

    1. Use code similar to the following:

      ' The account balance.
      Public Property Balance As Decimal
  • Add Debit and Credit methods to add and remove money from the account.

    1. Start with code similar to the following. You'll modify the Debit method later to raise the Overdrawn event.

      ' Add money to the account.
      Public Sub Credit(ByVal amount As Decimal)
          Balance += amount
      End Sub
      
      ' Remove money from the account.
      Public Sub Debit(ByVal amount As Decimal)
          Balance -= amount
      End Sub
  • Define the AccountOverdrawnArgs class to pass the current and invalid balances to event handlers.

    1. Use code similar to the following:

      ' Define the OverdrawnEventArgs type.
      Public Class OverdrawnEventArgs
          Public Property CurrentBalance As Decimal
          Public Property InvalidBalance As Decimal
      End Class
  • Declare the Overdrawn event.

    1. Use code similar to the following:

      ' Declare the Overdrawn event.
      Public Event Overdrawn(ByVal sender As Object,
       ByVal e As OverdrawnEventArgs)
  • Make the Debit method raise the event when necessary.

    1. Modify the simple initial version of the method so it raises the event when necessary. Use code similar to the following:

      ' Remove money from the account.
      Public Sub Debit(ByVal amount As Decimal)
          ' See if there is enough money.
          If (Balance >= amount) Then
              ' There is enough money. Just do it.
              Balance -= amount
          Else
              ' There's not enough money.
              ' Make an OverdrawnEventArgs to describe the event.
              Dim args As New OverdrawnEventArgs()
      args.CurrentBalance = Balance
              args.InvalidBalance = Balance - amount
      
              '  Raise the Overdrawn event.
              RaiseEvent Overdrawn(Me, args)
          End If
      End Sub
  • In the main program, declare the MyAccount variable using the WithEvents keyword.

    1. Use code similar to the following:

      ' Declare an account.
      Private WithEvents MyAccount As BankAccount
  • In the main program, catch the Overdrawn event and display a message.

    1. Use code similar to the following:

      ' We're overdrawn.
      Private Sub MyAccount_Overdrawn(ByVal sender As Object,
       ByVal e As BankAccount.OverdrawnEventArgs) _
       Handles MyAccount.Overdrawn
          MessageBox.Show("Insufficient funds.")
      End Sub

Note

If you don't need to use the event handler's parameters, you can use relaxed delegates to remove them and make the code simpler as in the following code:

' We're overdrawn.
Private Sub MyAccount_Overdrawn() Handles MyAccount.Overdrawn
    MessageBox.Show("Insufficient funds.")
End Sub

Note

Please select Lesson 24 on the DVD to view the video that accompanies this lesson.

EXERCISES

  1. The version of the BankAccount class used by this lesson's Try It allows the main program to directly get and set the Balance property, and that could lead to errors. For example, if the program directly sets Balance = −10, the class would not have a chance to raise the Overdrawn event.

    To fix this problem, copy the program you built for this lesson's Try It or download the version available on the book's web site. Convert the Balance property from an auto-implemented property to one implemented with a backing field. Add the keyword ReadOnly before the property's Public keyword and remove the property set procedure. Now the only way to set the balance is through the Credit and Debit methods. (Hint: You may need to fix some code that tries to set Balance directly. Inside the BankAccount class, use the backing field. Outside the class, use the Credit method.)

  2. Make a Student class that has a Name property (a String) and a private TestScores field (a List of Integers). Give it a ReadOnly Average property that calculates and returns the Student's test average. Also give it an AddScore method that adds a score to the list. If the Student's new average is below 60, raise a FailureWarning event, passing the new average as a parameter. Hint: Initialize the TestScores field when you declare it, as in:

    Private TestScores As New List(Of Integer)()
  3. Make a Player class with Name and Points properties. Make a ReadOnly property Level that returns Points 10. In the Points property set procedure, raise a LevelUp or LevelDown event every time the Level changes.

    Note

    You can find solutions to this lesson's exercises in the Lesson24 folder inside the download available on the book's web site at www.wrox.com or www.vb-helper.com/24hourvb.html.

EXERCISES
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset