home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Advanced Visual Basic Techniques
(Publisher: John Wiley & Sons, Inc.)
Author(s): Rod Stephens
ISBN: 0471188816
Publication Date: 06/01/97

Search this book:
 
Previous Table of Contents Next


AppointmentBook stores the objects and their event masks in the Views and Events collections. Adding a new view to the list with RegisterView is simple.

Private Views As New Collection
Private Events As New Collection
    :
Public Sub RegisterView(view As Object, event_mask As Long)
    Views.Add view
    Events.Add event_mask

End Sub

When an event occurs, the model must notify the interested views. The NotifyViews subroutine described in the earlier section, “Bit Masks in AppointmentBook,” does this. It takes as a parameter a mask indicating which event or events just took place. For each view interested in the events, Notify-Views invokes the object’s Notify subroutine.

Private Sub NotifyViews(event_mask As Long)
Dim i As Integer

    For i = 1 To Views.Count
        ‘ Notify this view if necessary.
        If event_mask And Events.Item(i) Then _
            Views.Item(i).Notify event_mask
    Next i
End Sub

Finally, if views may eventually be destroyed by a program, the model should provide an UnregisterView subroutine. When a view no longer needs to be informed of the model’s events, the program should use UnregisterView to remove it from the model’s list of views. This is important for preventing the model from trying later to invoke the Notify subroutine of an object that no longer exists.

Public Sub UnregisterView(view As Object)
Dim i As Integer

    For i = 1 To Views.Count
        If view Is Views.Item(i) Then
            ‘ Remove this view and its event mask.
            Views.Remove i
            Events.Remove i
            Exit Sub
        End If
    Next i
End Sub

At first one might think a view object’s Class_Terminate event handler would be an ideal place to call UnregisterView. Then when the program destroyed an object, the call would happen automatically.

Unfortunately, this does not work. Visual Basic does not invoke an object’s Class_Terminate event handler until the object is actually destroyed. Visual Basic will destroy an object only when the program contains no more references to the object. Because a view object is included in the model’s list of views, the program contains a reference to the object so the Visual Basic will not destroy it. Therefore, the Class_Terminate event will not occur, so the call to UnregisterView will not happen.

To destroy a view object correctly, the program must first call UnregisterView and then destroy the object. The following code shows how a program could destroy a view of the MyView class”

Dim my_view As MyView
        :
    ‘ Initialize my_view, register it, etc.
    Set my_view = New MyView
    :
    ‘ Destroy my_view.
    TheModel.UnregisterView my_view
    Set my_view = Nothing

Model Summary In summary, the model class must understand the application data. It must provide subroutines, functions, and property procedures that allow other parts of the program to view and modify the data. Finally, it must notify views when the data changes.

The model does not need to know why another part of the program needs to view or modify the data. It also does not need to understand why views are interested in different events. For example, when it changes the selected date, the model notifies the views that are interested in that event. It does not understand the complex series of changes this may cause.

Views

A view object has only one responsibility: to provide some sort of display of a model. A view uses the model’s public routines and property procedures to obtain information about the data so it can present an appropriate display. Usually this display is visible through a user interface, though in theory the display could provide information to another program rather than the user.

The view should be registered with the model so it receives notification whenever a change to the data would affect the view’s display. When the view receives notification, it should update its display as necessary.

Before a view object can receive event notifications, the program must register the view with the model, specifying the events that it finds interesting. A reasonable place to do this is in a view class subroutine named Initialize. This routine can take as parameters the model and any other information the view needs for initialization.

The DateLabelV class in AppointmentBook is a very simple view that manages the date display label above the daily appointment area. This label displays the currently selected date textually. When the user drags the month area’s scroll bar slider, this label displays the date that would be selected if the user were to release the slider.

AppointmentBook’s main form CalendarForm uses code similar to the following to declare and initialize the variable TheDateLabelV. This is the date label view object used by the program to manage the date label.

‘ Declare the view.
Private TheDateLabelV As New DateLabelV
         :
    ‘ Initialize the view.
    TheDateLabelV.Initialize TheCalendarModel, DateLabel

The Initialize subroutine for the DateLabelV class takes as parameters the model and the label control that will later display the selected date. The routine saves references to these for later use. It then registers itself with the model indicating that it should be notified when the selected date changes and when the “temporary date” changes. The temporary date is the date selected while the user is dragging the month area’s scroll bar slider.

Public Sub Initialize(model As Object, ctl As Label)
    ‘ Save the label control for later use.
    Set TheLabel = ctl

    ‘ Save the model for later use.
    Set TheModel = model

    ‘ Register with the calendar model.
    model.RegisterView Me, _
        CAL_SelectedDateChanged Or _
        CAL_TemporaryDateChanged
End Sub

Controllers

A controller manipulates the data in a model. The controller must manipulate the data indirectly using the public routines provided by the model. Those routines modify the data as needed and then notify any views that are interested in the change. If a controller were to modify the data directly, the model would not have the opportunity to notify the views.

Sometimes a controller may need to make several changes to the data before the model notifies the views. When performed individually, the changes might cause notification to be sent several times to the same views. That, in turn, might force a view to redraw itself several times unnecessarily.

In cases like this, it is tempting to provide routines in the model that do not perform view notification. The controller would use those routines until the last modification, when it would use the normal data modification routine. This is not a wise practice. If the last call to the normal modification routine is omitted or later removed, the views will never be updated.

A better solution is to create a new model subroutine that performs all of the data modifications in a single subroutine call and then notifies the views when it is finished.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.