Iterating Through dataform1 Elements
The technique for iterating through dataform1 elements is slightly different to that used in the wxform. Firstly, there are many different dring properties: controls, graphics, bitmaps, tables, datasources, detailblocks, links, siblinglinks, obgroups, and pages. Iterating through these drings is fairly consistent, but you need to know what to expect from each one, so that the varialbe used to hold the current item is correctly defined. Below is a table showing the dring and the type that a variable must be declared as in order to hold any given member of the dring.
Ring Property Name | Required Type |
---|---|
controls | type(dataform1control) |
graphics | type(dataform1graphic) |
bitmaps | dataform1bitmapsource |
tables | dataform1table |
datasources | dataform1datasource |
detailblocks | dataform1detailblock |
links | dataform1link |
siblinglinks | dataform1link |
obgroups | dataform1optiongroup |
pages | dataform1page |
In each case the approach is the same:
function collectdf1controlnames(dataform1 f) type(dataform1control) c string names names = "" c =@ f.controls.getfirst() while c !@= .nul names = names + c.name + "{d}{a}" c =@ c.formnode.getnext() end while c =@= f.controls.getfirst() end function names
In each case, the code tends to look very similar. It starts by getting the first
item in the ring, then if that is not null (the ring has at least one entry), it
enters the loop, processes whatever it is doing (the purpose for going through all
the entries), then retrieves the next one in the ring, finishing when it has reached
the first one again. In the prior example, since any number of different control
types will be returned by the call to c.formnode.getnext()
, the
variable c
is declared with the method used for defining a
variable that can contain a type-tagged group of types. The type tag
dataform1control is not a type, it is a type tag associated with
each dataform1control in its type definition, to enable exactly this
sort of functionality. For further information about type tags see the section called “Value Types, Reference Types, and Type Tags”.
Most of the types have a formnode property, which contains the reference to the dlistnode that makes the item part of the ring. Some items have a different name, and some have more than one node, so selecting the correct one is essential. For example, the form controls have a formnode and a pagenode (the dataform1option control also has a groupnode). To iterate through all the controls in the form, start with the dataform1 controls dring and use the formnode of each control to get the next one. To iterate through all the controls on a given page, use the controls property of the dataform1page and then use the pagenode of each control to get the next one. Here is an example that iterates through all pages on a form, and through each control on the page.
function df1pagesandcontrols(dataform1 f) dataform1page p type(dataform1control) c string info info = "" p =@ f.pages.getfirst() while p !@= .nul if info > "" info = info + "{d}{a}" end if info = info + p.name + "{d}{a}" + "-" * .len(p.name) + "{d}{a}" c =@ p.controls.getfirst() while c !@= .nul info = info + " " + c.name + ": type=" + c.type + "{d}{a}" c =@ c.formnode.getnext() end while c =@= p.controls.getfirst() p =@ p.formnode.getnext() end while p =@= f.pages.getfirst() end function info
In the preceding program the two iteration variables are p
and
c
. The page variable is defined to be of one specific type:
dataform1page, since that is the only type that is managed by the
ring. The other is defined as type(dataform1control), since all of the
various dataform1 control types will be in the ring and therefore
the variable needs to be able to hold a reference to any of them.