VERSIONS: All, written for Paradox 5
SUBJECT: Which table is the target for an event?
BY: MARK PAUKER
QUESTION:
In a form with fields from Master table placed on the page, how can I determine in which table an insert is about to happen.? I did not use a MRO
to display the master table - because it spans multiple pages.
You can use eventInfo.getTarget() to determine where the action is being sent, and then look at the target object's tableName property. The
problem with this approach is that not all uiObjects have a tableName property, and an unbound field's tableName property is blank (even though
any data action sent to it that bubbles up to the form will be applied to the DM's master table).
The following code should overcome both of these problems, but be sure to read the caveat below if you want to apply this to actions other
than DataInsertRecord:
eventInfo.getTarget(uiTarget)
while True
try
stTableName = uiTarget'tableName
if stTableName = "" then
fm.attach()
stTableName = fm'tableName
endIf
quitLoop
onFail
uiTarget.attach(uiTarget.container)
endTry
endWhile
If you know that the action will always be initiated by the user (rather than by OPAL) and that only fields are tabbable, then you could simplify
this by using "active" as follows:
stTableName = active'tableName
if stTableName = "" then
fm.attach()
stTableName = fm'tableName
endIf
If you further know that there are no unbound fields, then you can simply use:
stTableName = active'tableName
I suggested to Borland that they add an "activeTable" property to all uiObjects that would return the name of the table that would be effected if an
action was sent to that object. This would eliminate the need for all of this code. Unfortunately, there's a kicker that makes this quite difficult.
Most data actions, including DataInsertRecord, bubble up to the form before they are acted on. The form in turn determines the appropriate
table for the target object and takes the appropriate action. The problem is that if the target object is not _directly_ bound to a particular table,
Paradox doesn't bother looking up the containership hierarchy to see if the object is contained by an object bound to a table. It simply applies the
action to the data model's master table. This causes unwanted behavior in every scenario I can imagine, but can be worked around as long as we
know about it.
The real problem is that we cannot rely on this behavior being consistent. Some data actions (such as DataNextRecord) are carried out by
objects before they bubble to the form. Thus these actions are guaranteed to act upon the "correct" table, while the other actions are not. This
incongruity makes it impossible to determine what table will be effected when sending an action to an unbound object unless you know whether
or not that action will be acted upon before it bubbles up to the form.
For example, consider a form with 2 tables in its data model, Master and Detail, linked 1-to-M. Fields from Master are placed directly on the
form, and fields from Detail are placed in an MRO within the form. Now let's place an unbound field (or a button with its tabStop property set to
True) inside the detail's MRO and make that object active. Pressing the "Next Record" button will cause Paradox to attempt to move to the next
detail record because the action will be handled by the MRO as it bubbles up the containership path. Conversely, pressing Ins will insert a new
_Master_record because the action will continue bubbling past the MRO to the form, and the form won't bother to determine that the object is
contained within the MRO.
I realize this is probably more of an answer than you were looking for, but unfortunately, it's a bit more complex than it appears. The good
news is that if all tabbable objects on your form are bound fields, the whole thing becomes somewhat trivial.