(c) Copyright 2000-2003 SDGN / Viafox, All rights reserved

Het artikel 'Activating the Refresh' is gepubliceerd in SDGN-Magazine nr. 57. De onderstaande, originele, tekst wijkt iets af van het gepubliceerde artikel en is feitelijk beter omdat in het gepubliceerde artikel de schema's een te klein gebied kregen toegewezen om effectief te kunnen worden geraadpleegd.

Activating the Refresh

Copyright Viafox

Een van de lastiger klussen is het adekwaat verversen van de objecten. Adekwaat wil hier zeggen dat het precies op tijd moet gebeuren en ook slechts eenmaal. In de praktijk overkomt het mij geregeld dat een objectwaarde of ‑eigenschap onder bepaalde omstandigheden zou moeten veranderen en dat dan toch niet elke keer blijkt te doen. Of de verversing gebeurt wel, maar dan soms meer dan eens. Zo'n overdadige afhandeling wordt vaak niet eens door de programmeur opgemerkt, maar gaat mogelijk wel ten koste van de performance en zal, zo het later door een collega wordt ontdekt, niet echt als fraai programmeerwerk worden beschouwd. Wat gaat er mis?

 

Eerst even schetsen wat ik dan veelal programmeer. Als ik wil dat een objectwaarde of –eigenschap bijgesteld wordt op grond van een gebeurtenis elders in het venster, dan zal ik veelal de Refresh Method van het bij te stellen object aanroepen. En als het om meerdere objecten tegelijkertijd gaat, zal ik mogelijk een aanroep doen van een of andere method van de container waarin die objecten verblijven. En in die method worden dan weer de Refresh Methods van de te verversen objecten aangeroepen. Crux is de plek waar die aanroep geschiedt goed te kiezen. En daar zit 'm eigenlijk de pijn, want dat is niet altijd even makkelijk. Wie redundantie in de code wil vermijden, zal al snel diverse 'paden' definiëren. Stel dat er een rits aankruisvakken in het venster zijn en dat een wijziging in welke van die aankruisvakken dan ook al tot verversing van het venster moet leiden, dan zou je natuurlijk in ieders Click Method alle te verversen objecten kunnen afhandelen, maar het lijkt me al handiger om ieders Click Method een daarvoor aangewezen method te laten aanroepen en die method dan de verversingen te laten doen. Mogelijk besteedt deze method het werk ook weer uit aan een of meer andere methods, vandaar mijn notie over 'paden'. Die aangeroepen method zou een native method kunnen zijn, maar ook eentje die de programmeur zelf heeft gecreëerd.

 

Afijn, de vraag was: Wat gaat er mis? Dan wil ik toch eerst nog even een ander principe uitleggen. Wat ik hierboven beschrijf impliceert, ook in het geval dat een centrale method de Refresh Methods aanroept, uiteindelijk nog steeds dat elk te verversen object apart aangeroepen wordt. Echter, eigenlijk is het onhandig geklungel als je elk object middels een aparte aanroep van diens Refresh Method ververst. Zoiets doe je alleen als het om een of twee specifieke objecten gaat. Bij meer gevallen zoek je al snel je toevlucht tot de Refresh Method van de container waar de objecten toe behoren. Aanroepen van diens Refresh Method induceert namelijk ook de aanroep van de onderliggende Refresh Methods! Dat is handig en waarborgt dat objecten die verwijderd worden of er later bij komen niet voor nieuwe problemen zorgen.

 

Afijn, wat gaat er mis? Nee, eerst nog een ander principe ook noemen. Mogelijk heb je gekozen voor een venster met tabbladen. We hebben dan niet alleen de 'container' Thisform, maar ook de 'container' Pageframe1 en de 'containers' Page1, Page2, enzovoort. Die hebben ieder een eigen Refresh Method. Maar bovendien hebben Thisform en de diverse Pages de methods Activate en Deactivate. En dat zijn methods die door VFP bezocht worden onder bepaalde omstandigheden, ofwel het zijn Events. (Onthoud dat Refresh Methods gèèn Events zijn!) Van die eigenschap willen we soms graag gebruik maken. Stel dat op alle tabbladen objecten staan die in theorie moeten worden ververst als op tabblad 1 in een Grid-object een volgende regel wordt geselecteerd, dan stel ik me zo voor dat je die verversing op dat moment inderdaad wilt realiseren voor tabblad 1, maar dat je er nog even mee wilt wachten voor wat betreft de andere tabbladen. Dat zou weleens flink in de performance kunnen gaan schelen. Sommige tabbladen worden misschien maar zelden door de gebruiker bekeken en waarom zouden we met de verversing niet gewoon wachten tot de gebruiker op dat tabblad klikt?! Ok, dat kunnen we realiseren. Stel dat het om pagina 3 gaat, dan zouden we Page3.Refresh kunnen aanroepen vanuit de Page3.Activate Method.

 

Ok, weten we nu genoeg? De vraag was: Wat gaat er mis? Waarom worden objecten niet altijd goed ververst? Of juist te vaak? Het antwoord is dat er in theorie niks mis gaat, als je maar een goed besef hebt van de manier waarop Refresh (geen Event) en Activate (wel een Event) in VFP geïmplementeerd zijn. En het viel in elk geval mij niet mee om dat besef te ontwikkelen. Er zitten namelijk kanten aan die in strijd zijn met mijn intuïtie. Wat dacht je van het volgende citaat uit de documentatie: 'When a form is refreshed, all controls on the form are also refreshed. When a page frame is refreshed, only the active page is refreshed.' Deden die jongens bij Microsoft hier nou echt goed aan? Het lijkt handig, maar maakt dingen minder intuitief. Ander voorbeeld: Je hebt tabblad 2 actief en klikt dan buiten het venster (dus buiten de Form). Vervolgens klik je weer in het venster, maar dan op tabblad 3. Ziehier de volgorde van Activate/Deactivate methods die op dat moment aangedaan worden: Page2.Activate, Thisform.Activate, Page2.Deactivate en dan pas Page3.Activate. Snapt u?

Het zijn nu precies dit soort tegen de intuïtie in gaande principes die ervoor zorgen dat het zo makkelijk mis kan gaan. Je blijkt dan net even de verkeerde methods de net even verkeerde aanroepen te laten doen. Dingen worden dan onder omstandigheden, bijvoorbeeld bij klikken op een ander tabblad, dubbel gedaan of juist helemaal niet gedaan. Dus als het mis gaat, zul je weer aan de bak moeten. En daarbij zouden de schema’s van dit artikel je weleens zeer van nut kunnen zijn.

 

De schema's betreffen een werkmodel. Een werkmodel beschrijft niet per sé de theorie; Het is de bedoeling dat het model voorziet in een praktische behoefte tijdens de werkzaamheden. Je kunt erin vinden in welke volgorde VFP de Refresh en Activate methods zal afwandelen. Leg de schema's op je bureau of plak ze aan de wand. Bij twijfel werp je een blik op de schema's en je zult veel gemakkelijker de methods kunnen lokaliseren waar de Refresh-aanroepen idealiter gerealiseerd moeten worden.

 


Het Refresh Model in Visual FOXPRO

·         VFP roept zelf het stelsel van Refresh Methods niet automatisch aan, ook niet bij het initieel neerzetten van de objecten. Het stelsel is alleen programmatisch aan te roepen.

·         Aanroepen van een Refresh Method induceert ook de aanroep van onderliggende Refresh Methods.

 

 

Bij aanroep van de Refresh Method van de Form volgt…

1.        Aanroep van Refresh Methods van objecten op Form-niveau, waaronder de Pageframe;

2.        Alleen aanroep van de Refresh Method van de Active Page;

3.        Aanroep van de Refresh Methods van de objecten op de Active Page.

 

Bij aanroep van de Refresh Method van de Pageframe volgt…

1.        Alleen aanroep van de Refresh Method van de Active Page;

2.        Aanroep van de Refresh Methods van de objecten op de Active Page.

 

Bij aanroep van de Refresh Method van een Page (actief of inactief) volgt…

1.        Aanroep van de Refresh Methods van de objecten op de Page.

 

Bij aanroep van de Refresh Method van een Container volgt…

1.        Aanroep van de Refresh Methods van de objecten in de Container.


Het Activate Model in Visual FOXPRO

 

·         VFP roept zelf het stelsel van Refresh Methods niet automatisch aan, dus ook niet vanuit de Activate Methods. De twee modellen staan dan ook geheel los van elkaar, zolang een programmeur niet expliciet een Refresh Method aanroept vanuit een Activate Method.

·         Programmatisch aanroepen van een (De)Activate Method induceert niet de aanroep van onderliggende (De)Activate Methods.

 

 

Als je de Form activeert door buiten de Pageframe of op een object in de Active Page (X) te klikken:

 


 

Als je de Form activeert door op een object in een andere Page (Y) te klikken:

 


 

 

Als je binnen de Form binnen of buiten de Pageframe bent en dan op een andere Page (Y) klikt:

 


 


Als je binnen de Form buiten de Pageframe bent en dan op een object in de active Page (X) klikt:

 


 

 

Home