ich bin vor kurzem über Deinen alten Tipp mit den Unterformularen gestoßen. Und ja, es ist eine coole Sache und funktioniert erstaunlich gut.
Aber wozu braucht man den Event „on bound variable change“ ?
Es funktioniert bei mir alles in meiner TestumgebungUnterformular auf Maske setzen, Ausgabelayout auskreuzen, paar Events anhaken, Tabelle und Formular zuweisen, richtig positionieren fertig.
Was übersehe ich dabei ?
Ein Unterformular ist ein Objekt im Master-Formular. Dem Objekt ist eine Variable zugewiesen. Den Datentyp kann ich festlegen, meistenteils nehme ich alphanumerisch oder numerisch. Ändere ich den Wert dieser Variablen feuert in der Formmethode des Unterformulars On Bound Variable Change. Das ist eine einfache Form der Kommunikation.
Habe ich eine Listbox mit Datensätzen und ein Unterformular mit den Feldern eines Datensatzes, dann ändere ich in On Selection Change der Listbox den Wert der Unterformular-Variablen auf die Datensatz-ID der neu ausgewählten Listbox-Zeile.
Das Unterformular bekommt die Änderung mit. Im Unterformular sichere ich den aktuellen Datensatz und lade oder suche den nun gebrauchten. Das sind diese Zeilen in der Subform-Methode
SAVE RECORD([TABLE])
QUERY([TABLE];[TABLE]KeyFeld=$P_boundObj->)
// nun meine ausgelagerte On Load
Per Macro lasse ich diese Zeilen für die Datentypen alphanumerisch und numerisch in den passenden Absatz der Formmethode einsetzen:
: (Form event=On Bound Variable Change)
$P_boundObj:=OBJECT Get pointer(Object subform container)
Case of
: (Nil($P_boundObj))
: ((Type($P_boundObj->)=Is text) | (Type($P_boundObj->)=Is string var) | (Type($P_boundObj->)=Is alpha field))
: ((Type($P_boundObj->)=Is longInt) | (Type($P_boundObj->)=Is integer) | (Type($P_boundObj->)=Is real) | (Type($P_boundObj->)=Is integer 64 bits))
Else
End case
Die zwei Zeilen mit SAVE RECORD und QUERY sind an der passenden Case of-Option einzusetzen.
Spannender wird der On Bound Variable Change-Event, wenn man die Subform wie ein unabhängiges Objekt denkt. Die Variablen der Subform haben der Masterform unbekannt zu sein, dito die Datenstruktur. Denke ich in abgeschlossenen Objekten, kann ich das UI alter Datenbanken in Richtung Ein-Fenster-Oberfläche modernisieren, ohne mich um die bewährten Funktionalität kümmern oder gar in diese eingreifen zu müssen.
Den Gedanken eines 4D-UI-Modernizr an dieser Stelle auszuspinnen überfordert das Medium nicht zu langer Texte – ein Seminar, vielleicht ein multimediales eBook, wenn es sich bezahlt macht.
these days I stumbled across your older tip concerning subforms. Indeed, very cool and works perfectly well.
But what do I need the form event „on bound variable change“ for?
It works in my testing environment:place a subform on main-form, uncheck listform, check sample of events, name tableform or projectform, place properly.
What am I overlooking ?
A subform is an object inside a masterform. A variable is attached to every subform. The datatype is to be defined, mostly alphanumeric or numeric will fit. As soon as I change the value of the variable the subform will get an On Bound Variable Change-event. This is a simple form of communication.
Suppose there is a listbox of records and a subform for a single-record display and edit. In On Selection Change-event of the listbox the subform-variable is set to the new record-id value.
The subform needs to react on this event. In this case, save the current record and query or load the one corresponding to the bound-variable value. Shown here for an array-listbox
SAVE RECORD([TABLE])
QUERY([TABLE];[TABLE]KeyFeld=$P_boundObj->)
// now call my On Load-procedure, which is not confined to On Load, of course
Usually a macro pastes these lines at the right place of the formmethod – both for alphanumeric and numeric:
: (Form event=On Bound Variable Change)
$P_boundObj:=OBJECT Get pointer(Object subform container)
Case of
: (Nil($P_boundObj))
: ((Type($P_boundObj->)=Is text) | (Type($P_boundObj->)=Is string var) | (Type($P_boundObj->)=Is alpha field))
: ((Type($P_boundObj->)=Is longInt) | (Type($P_boundObj->)=Is integer) | (Type($P_boundObj->)=Is real) | (Type($P_boundObj->)=Is integer 64 bits))
Else
End case
The two lines with SAVE RECORD and QUERY are to be placed at the appropriate Case of-option.
Besides communication the On Bound Variable Change-event serves me well, when thinking of a subform as an independet object. The variables of the subform are unknown to the masterform, same is true for the data-structure. Thinking the ideas of self-contained objects, proven database apps can be modernized towards a single-window-UI without really touching any code.
Spinning out the idea of a 4D-UI-Modernizr isn’t suitable for this medium – a seminar maybe, maybe a multimedia eBook, if they pay.