Data Binding in Forms
In KCML6.10, the binding of controls to data was enhanced to provide extra functionality but the original data aware mechanisms continue to work. The changes are to the way the data source is referenced by the form and are to allow for more control at run-time than was previously possible.
Under the old scheme the table browser in the forms editor lists the tables used by the form and it allows the user to expand the tables to see the columns. Column entries may be dragged from the table window onto a form where a dbedit with a label is created. The original list of tables is determined by the DEFOBJ statements in the program and the list of columns for each table are determined by reference to the dictionary schemas specified in these DEFOBJ statments.
In the new scheme any DEFRECORD can be used to define data awareness, which removes the restriction that data awareness could only be done against database tables and opens it up to allow data aware structures. Each DEFFORM contains the data sources used for the form as data binding pseudo-controls (this is similar to how colors, fonts and pictures are managed), rather than using separate DEFOBJ statements. Extra bindings for a form can easily be added in the workbench, by dragging a record from the browser window directly onto a DEFFORM statement in the editor window. The forms editor will list the available tables for the form, and controls can be dragged onto the form in the usual manner. The .DataField$ property of the control is updated by the forms editor to be the names of the field as a string. The label for the control is taken from the comment for the FLD (this is a REM statement immediately following the FLD statement. The variable to be bound is exposed through the Bind property of the DataBind object and is defaulted to be the same as the name of the record
Programmatically there are several advantages to the new scheme, as the data binding can be now be done dynamically using new variants of the SetDataField() method. Firstly, SetDataField now applies to all data aware controls and not just grid cells. Secondly, instead of passing start and pack formats, SetDataField can also take a single string argument specifying the name of the record and the values are deduced from the DEF RECORD statement. Finally, the data source for a control can now also be defined programmatically, by associating it with a particular data bind control in the same manner as picture items.
.myControl1.DataBind = &.data_sl_ac_accts .myControl1.SetDataField(10, "DATE") .myControl1.SetDataField("ACCOUNT_NAME") .myGrid1.cell(10,10).SetDataField(10, "DATE") .myGrid1.cell(10,10).SetDataField("ACCOUNT_NAME")
This example shows a program with two records used to instantiate two buffers. Both records were dropped onto the form in the forms editor whose table view dialog will display two tables. One table was used to populate an edit group with four dbedits by dragging off the table view and dropping into the edit group. Note how the REM comments associated with the FLDs have been used as the label text for the dbedits. The second table is not used and is left as an example to the reader.
REM the main record, note the REMs so we get labels on the form DEFRECORD one FLD numval = "NUM(7,2)" : REM Value FLD desc$16 : REM Description FLD now = "DATE" : REM Purchase date FLD actual$ = "TIMESTAMP" : REM Transactional timestamp END RECORD REM the bound buffer for the record DIM one$_one REM initial values FLD(one$.now) = #DATE FLD(one$.actual$) = $TIMESTAMP FLD(one$.desc$) = "Hello" FLD(one$.numval) = 1.345 REM another record, so we can have a choice DEFRECORD two FLD price : REM Price FLD partno$12 : REM Part number END RECORD DIM two$_two - DEFFORM BoundForm()={.form,.form$,.Style=0x50c000c4,.Width=405,.Height=251,.Text$="Form",.Id=1024},\ {.ok,.button$,.Style=0x50010001,.Left=349,.Top=6,.Width=50,.Height=14,.Text$="OK",.__Anchor=5,.Id=1},\ {.cancel,.button$,.Style=0x50010000,.Left=349,.Top=23,.Width=50,.Height=14,.Text$="Cancel",.__Anchor=5,.Id=2},\ {.help,.button$,.Style=0x50010000,.Left=349,.Top=44,.Width=50,.Height=14,.Text$="&Help",.__Anchor=5,.Id=9},\ {.editgroup1,.editgroup$,.Left=37,.Top=28,.Width=280,.Height=134,.Id=1000},\ {.actual,.kcmldbedit$,.Style=0x50810080,.Left=163,.Top=45,.Width=134,.Height=13,.Id=1001,.EditGroup=.editgroup1,.Label$="Transactional timestamp:",.DataBind=.data_one,.DataField$="actual$"},\ {.desc,.kcmldbedit$,.Style=0x50810080,.Left=163,.Top=69,.Width=134,.Height=13,.Id=1002,.EditGroup=.editgroup1,.Label$="Description:",.DataBind=.data_one,.DataField$="desc$"},\ {.now,.kcmldbedit$,.Style=0x50810080,.Left=163,.Top=101,.Width=134,.Height=13,.Id=1003,.EditGroup=.editgroup1,.Label$="Purchase date:",.DataBind=.data_one,.DataField$="now"},\ {.numval,.kcmldbedit$,.Style=0x50810080,.Left=163,.Top=133,.Width=134,.Height=13,.Id=1004,.EditGroup=.editgroup1,.Label$="Value:",.DataBind=.data_one,.DataField$="numval"},\ {.data_one,.DataBind$,.Bind=one$,.Record=_one},\ {.data_two,.DataBind$,.Bind=two$,.Record=_two} FORM END BoundForm BoundForm.Open()
Data Aware Forms, DataBind object, SetDataField(), GetDataField()