Class DataRef() Foundation

Class function of the DataRef class.


The exclusive purpose of objects of the DataRef class is to reference data. Many Xbase Parts are derived from this class and the XbpWindow class. Since it has a visual representation and can access data, an Xbase Part is derived from XbpWindow as well as from DataRef. An Xbase Part can then manage both the screen display and the data.

The DataRef class provides services for other classes and is only significant in relation to other classes. A DataRef object is useless by itself. The service of a DataRef object is to reference data which is stored in variables (field variables or memory variables). This includes reading, assigning values to variables, data validation and the ability to undo changes made to the data.

The most important methods of a DataRef object are :setData() and :getData(). These two methods are used to define the current value in an Xbase Part edit buffer or to read the value and assign it to a variable. In this discussion of the DataRef class, the XbpSLE class is used to illustrate the DataRef class. The edit buffer of the XbpSLE object is set and read using :setData() and :getData(). The XbpSLE class is derived from DataRef and consequently these two methods also exist for XbpSLE objects. This can be shown in the following program code:

cText := "Copy characters into the edit buffer" 
oSLE:setData( cText ) 

// process events within SLE (Event loop) 

cText := oSLE:getData() 
? cText    // result: what the user has input 

This program code illustrates the use of the methods :setData() and :getData(). :setData() is used to pass data to the Xbase Part and :getData() is later used to read the data. In the meantime, data is processed by the user within the event loop.

In the example, an argument (the memory variable cText) is passed to the method :setData() and the return value of :getData() is assigned to the variable cText. This process can be automated by assigning a code block for data handling to the instance variable :dataLink:

cText := "Pass characters to the edit buffer" 
oSLE:dataLink := {|x| IIf( x==NIL, cText, cText := x) } 

// process events within SLE (Event loop) 

? cText    // result: whatever the user has input 

In this modified example, the data is passed between the memory variable and the Xbase Part using the data code block assigned to the instance variable :dataLink. When :dataLink contains a code block, this code block is evaluated by the method :setData() with no arguments. The value of the variable (the return value of the code block) is then sent to the Xbase Part. In the example, the value of cText is copied into the edit buffer of the input field oSLE. When :getData() is called, the current value of the Xbase Part is passed to the code block. The code block contained in :dataLink assigns the value to a variable referenced by the code block.

Class methods
Creates an instance of the DataRef class.
Instance variables
Indicates whether data has been changed.
Data code block of a DataRef object.
Result of the last data validation.
A code block executed by the method :undo().
Original value before the edit buffer was changed.
Code block for data validation
Returns the current value in the edit buffer of an Xbase Part.
Reads the current value of the edit buffer and passes it to :dataLink
Assigns a value to the edit buffer of an Xbase Part
Cancels the last edit operation
Validates the data in the edit buffer.
Xbase Parts and databases

// This illustrates the basic relationship of :dataLink, 
// :validate, :setData(), :getData() and :undo() in an 
// example with two input fields (SLE) and two pushbuttons 
// (PB). The SLEs allow editing of the two fields and the 
// PBs move the record pointer. The UDF WriteSkip() performs 
// record locking, validating, writing, skipping and re-reading 
// the data. 

#include "" 
#include "" 

   LOCAL nEvent:=0 , mp1, mp2, oXbp 
   LOCAL oSle1, oSle2 
   FIELD LName, FName 


   USE Customer 

   // create two SLEs for editing the fields 
   oSle1 := XbpSle():new( ,, {110,230}, {210,25} ) 
   oSle1:dataLink := {|x| IIf( x==NIL, LName, LName:=x ) } 
   oSle1:validate := {|o| ! Empty( o:editBuffer() ) } 

   oSle2 := XbpSle():new( ,, {110,170}, {210,25} ) 
   oSle2:dataLink := {|x| IIf( x==NIL, FName, FName:=x ) } 
   oSle2:validate := {|o| ! Empty( o:editBuffer() ) } 

   // create two pushbuttons for skipping 
   oXbp := XbpPushButton():new ( ,, {110,80}, {100,30} ) 
   oXbp:caption  := "~Next" 
   oXbp:activate := {|| WriteSkip( {oSle1, oSle2}, 1 ) } 

   oXbp := XbpPushButton():new ( ,, {220,80}, {100,30} ) 
   oXbp:caption  := "~Previous" 
   oXbp:activate := {|| WriteSkip( {oSle1, oSle2},-1 ) } 

   DO WHILE nEvent <> xbeP_Close 
      nEvent := AppEvent( @mp1, @mp2, @oXbp ) 
      oXbp:handleEvent( nEvent, mp1, mp2 ) 

// write data from the Xbase Parts into the file before 
// moving the record pointer 
PROCEDURE WriteSkip( aXParts, nSkip ) 
   LOCAL i, imax, oXbp 

   IF DbRLock( Recno() )            // lock data record 
      imax := Len( aXParts ) 
      FOR i:=1 TO imax 
         oXbp := aXParts[i] 
         IF oXbp:validate()         // validate data 
            oXbp:getData()          // write data to file 
            oXbp:undo()             // validation failed 
      DbRUnlock( Recno() )          // release lock 

   DbSkip( nSkip )                  // move record pointer 

   FOR i:=1 TO imax 
      aXParts[i]:setData()          // assign fields to XBPs 

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.