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