6.4 Synchronization Between Model and View

Automatic synchronization between Model and View is controlled by the .dataoptions[] attribute.

Table 16-6: Options for synchronization between Model and View

Attribute Index

Default

Component

Meaning

dopt_represent_on_map

true

View

Immediately before the View is made visible, the data values are fetched from the Model components and set on the View object.

dopt_represent_on_init

false

View

During object initialization (:init method), the data values are retrieved and set on the View object.

dopt_apply_on_unmap

false

View

Immediately before the View is made invisible, the data values are fetched from the View object and assigned to the linked Model components.

dopt_apply_on_event

false

View

If a user interaction triggers a dialog event which indicates a possible change of a View attribute, this is assigned to the linked Model components.

dopt_propagate_on_start

true

Model

When a dialog or module is started, the data from the Model objects is forwarded to the linked View components.

dopt_propagate_on_changed

true

Model

Modifications to a Model attribute are forwarded to the linked View components.

dopt_cache_data

true

Model

This index value is only available for the doccursor.

true

The data selected by the doccursor is buffered for further accesses (caching).

false

With each access, the doccursor selects the data anew from the XML Document.

A key feature of the Datamodel is that data changes are always signaled and processed asynchronously via the event processing. For example, if the Data Model (Model object) is a record or another object with user-defined or predefined attributes, an attribute change, which is signaled by a datachanged event, is transmitted to the linked View objects so that they can update themselves. The dialog programmer can suppress a changed event with the operation ::=, but never a datachanged event.

A global variable may be used as a Model component as well, but does not allow controlling the synchronization. Variable values s are always propagated when the dialog or module is started and when the variable value is changed.

When .dataoptions[dopt_apply_on_unmap] := true; is used on a dialogbox, messagebox or filereq via a querybox call, the data values are only transferred from the View to the Model in case of a positive confirmation (button_ok or button_yes).

Manual intervention is not necessary in most cases. However if required, manual synchronization can be accomplished using the following methods:

Table 16-7: Manually callable Datamodel methods

Method

Component

Function

:represent()

View

The data of all linked Model attributes (.dataget) is retrieved and assigned to the View object

:apply()

View

The data from all linked View attributes (.dataset) is fetched and assigned to the Models

:propagate()

Model

The Model object communicates a change of all its Model attributes to the View objects that have a linkage.

:collect()

Model

The Model object fetches all data from the linked View objects to assign it to its Model attributes.

Synchronization only happens between instances, never with Default objects or Models.

For optimized synchronization of partial values, there is another particular feature. If a value change is signaled, the index of this value change is forwarded so that only this single value needs to be updated by the View component.

Example

Through a timer object, random colors are picked and assigned to random table cells.

dialog D
color CoRed "red";
color CoYellow "yellow";
color CoGreen "green";
color CoBlue "blue";

timer TiRandomColors {
  .active true;
  .starttime "+00:00:00";
  .incrtime "+00:00:00'100";
  object Color[index] := null;

  on select
  {
    variable index RandIndex := [1 + random(5),1 + random(5)];
    variable object RandColor := D.color[1 + random(D.count[.color])];
    /* change the color at a specific index */
    this.Color[RandIndex] := RandColor;
  }
}

window Wi
 {
  .title "Datamodel - random colors";
  .width 400;  .height 400;

  tablefield Tf
  {
    .xauto 0;  .yauto 0;
    .rowcount 5;  .colcount 5;
    .colwidth[0] 60;  .rowheight[0] 30;
    .dataoptions[dopt_represent_on_map] false;  /* avoid initial :represent() */
    .datamodel TiRandomColors;
    .dataget[.bgc] .Color;
  }
}

This is the screenshot for it:

Figure 16-31: Randomly colored tablefield cells with a timer as Data Model