[AccessD] Building a control class

A.D.Tejpal adtp at airtelmail.in
Mon Mar 16 03:25:30 CDT 2009


John,

    Thanks for your generous observations and kind words. I had been procrastinating active study of classes, setting it aside for some future date. Some time back, in another thread, Gustav had pointed out the benefit of using WithEvents. Your lecture series has been instrumental in my getting further into it. It is an exhilarating experience and I can't thank you enough.

    The problem of projecting form class events into control class has since been resolved. It was found to be a matter of timing the instantiation, which should have been done in the property procedure (in control class) meant for setting the parent class property. Incidentally, for raised events, even though pertaining to form object, hooking via "[Event Procedure]" is not involved.

    It is seen that one level of circular reference does in any case come into play in each control class while setting up the parent property. Using WithEvents qualifier for the object variable (in control class) meant for holding a pointer to parent class, should not impose any extra strain on inter-class reference status.

    If instead, an object variable (WithEvents) is used for setting a pointer either to the form object variable in form class or directly to the real form (via parent property of control object argument passed to control class in its Init subroutine), it results in a second level of circular reference, over and above that existing between control class and form class as stated in preceding para. Though it works, such a state of multiple intersecting circular references, is found detrimental to proper termination and deserves to be considered forbidden.

    In certain situations, trapping form class events in control class can have its advantages. For example, various types of controls might be required to have different response to form's current event. If it were to be handled purely within form' current event in form class, it would require a set of statements, each with a loop, to activate the methods of individual control class objects in the collection. Local action in control class, by trapping form class events appears to offer simpler alternative. As a general principle, in one to many class object relationship, local implementation on the many side, if feasible, looks preferable.

    Effectiveness of the approach outlined in previous para, has been tested for the following features:
    (a) Form navigation combo box with two way synchronization.  
    (b) Dynamic filtration of look-up list for combo box.

    Note:  It is observed that for (b) above, a combination of form's current event (applying unfiltered row source) and combo's enter event (applying filtered row source) is adequate. No other event appears to be needed (e.g. form's Load event and combo's Exit / GotFocus / LostFocus events).

Best wishes,
A.D. Tejpal
------------

  ----- Original Message ----- 
  From: John W Colby 
  To: Access Developers discussion and problem solving 
  Sent: Friday, March 13, 2009 03:08
  Subject: Re: [AccessD] Building a control class


  AD,

   >In your view, what could be the best strategy for projecting the 
  events pertaining to form object variable in form class, into the 
  control class ?

  In general a control class should not be aware of the form and 
  particularly its events.  If the form needs to have a control do 
  something in response to one of the form's events, you should expose a 
  method in the control class to call from the form's event.  Let's take 
  an example:

  I use a combo control to cause the form to select a record.  The form 
  and the combo should "stay in sync" or it is visually confusing.  IOW, 
  if the form moves to a specific record, the record selector combo should 
  "move to" and display that same record.  Obviously if the combo selects 
  a record, the form should move to that record.  The form and combo "stay 
  in sync".

  I created a "mSyncToForm(lngPKID)" method in the combo class.  In the 
  form's Current event the clsCboRecSel.mSyncToForm is called passing in 
  the form's PKID.  The combo class then causes the combo control to 
  display the record with that value in column 0.  Thus the combo "syncs" 
  to the form.

  OTOH, if the user selects a record that they want to move to, the form 
  should move to that record.  clsCboRecSel defines an Event 
  evAfterUpdate(lngPKID as long).  The clsCboRecSel raises the 
  'evAfterUpdate event in the combo's AfterUpdate event stub in the 
  class.  clsCboRecSel is declared Withevents back in the form.  An event 
  stub is created in clsFrm sinking evAfterUpdate.  When evAfterUpdate 
  fires, control passes back to the form's evAfterUpdate event stub and 
  the form has to grab a copy of the RecordsetClone, move to that record, 
  grab the bookmark, then set the form's bookmark to that bookmark, 
  causing the form to move to the right place.

  Notice that the clsCboRecSel doesn't need to know anything about the 
  form in either case.  It can sync to the form simply by exposing a 
  method for the form to call, and the form can sync to the record 
  selector simply by sinking an event raised by the record selector class.

  So the answer is to build functionality into the control class, and 
  expose that functionality via methods of the control class.  Raise 
  events in the control class as required to notify the form that the 
  control class did something that the form class might want to know about.

  Often times the control class behaviors simply don't matter to the 
  form.  For example my combo control wrapper class can be programmed to 
  open a specific list form in the dbl-click event so that the list behind 
  the form can be programmed.  The form that carries the combo control 
  doesn't care about that, in fact that is a behavior that might be useful 
  in any combo in any form.  It is the combo control classes' business, 
  not the form class' business.

  IMO classes really need to *try* to be independent of each other.  
  Sometimes it is not possible, sometimes specific sets of classes form a 
  system and need each other to perform the whole task.  On the other hand 
  even when they might need to know about each other, you should try to 
  use an interface - an exposed method or raising an event - to allow the 
  partner object to get something done.  Programming an interface helps to 
  disentangle the objects themselves.

  << Snipped - so as to comply with prescribed size limits in AccessD >>

  I have to say I am heartened to have you asking so many questions about 
  classes and events.  From your general Access knowledge level I long ago 
  assumed that you were probably way above me in this stuff.  From the way 
  you study stuff I assume that you soon will be anyway.  ;)

  John W. Colby
  www.ColbyConsulting.com


More information about the AccessD mailing list