6.4 Synchronisierung zwischen Model und View

Die automatische Synchronisierung zwischen Model und View wird über das .dataoptions[]-Attribut gesteuert.

Tabelle 19-8: Optionen zur Synchronisierung zwischen Model und View

Attribut-Index

Standard

Komponente

Bedeutung

dopt_represent_on_map

true

View

Direkt vor der Sichtbarschaltung werden von den Model-Komponenten die Datenwerte geholt und dem View-Objekt gesetzt.

dopt_represent_on_init

false

View

In der Objektinitialisierung (:init-Methode) werden die Datenwerte geholt und am View-Objekt gesetzt.

dopt_apply_on_unmap

false

View

Direkt vor der Unsichtbarschaltung werden die Datenwerte vom View-Objekt geholt und den gekoppelten Model-Komponenten zugewiesen.

dopt_apply_on_event

false

View

Wird durch eine Benutzerinteraktion ein Dialogereignis erzeugt, welches auf eine mögliche Änderung eines View-Attributs hinweist, so wird dieses den gekoppelten Model-Komponenten zugewiesen.

dopt_propagate_on_start

true

Model

Beim Start des Dialogs bzw. Moduls werden die Daten der Model-Objekte an die gekoppelten View-Komponenten weitergegeben.

dopt_propagate_on_changed

true

Model

Änderungen an einem Model-Attribut werden an die gekoppelten View-Komponenten weitergereicht.

dopt_cache_data

true

Model

Dieser Indexwert ist nur für den doccursor verfügbar.

true

Die vom doccursor selektierten Daten werden für weitere Zugriffe zwischengespeichert (Caching).

false

Der doccursor selektiert die Daten bei jedem Zugriff neu aus dem XML-Dokument.

Ein ganz wichtiges Merkmal des Datenmodells ist, dass Datenänderungen immer asynchron über die Ereignisverarbeitung gemeldet und abgearbeitet werden. Ist z.B. das Datenmodell (Model-Objekt) ein Record bzw. ein anderes Objekt mit benutzerdefinierten oder vordefinierten Attributen, so wird eine Attributänderung, die über ein datachanged-Ereignis signalisiert wird, an die verbundenen View-Objekte gemeldet damit diese sich aktualisieren können. Der Dialogprogrammierer kann zwar über die Operation ::= ein changed-Ereignis unterbinden, niemals aber ein datachanged-Ereignis.

Eine globale Variable kann ebenso als Model-Komponente verwendet werden, erlaubt aber keine Steuerung der Synchronisation. Es erfolgt bei Variablen immer eine Wertepropagierung bei Start des Dialogs bzw. Moduls und bei Änderung des Variablenwertes.

Wird .dataoptions[dopt_apply_on_unmap] := true; an einer Dialogbox, Messagebox oder Filereq über einen querybox-Aufruf genutzt, so erfolgt die Übertragung der Datenwerte von der View zum Model nur bei einer positiven Bestätigung (button_ok oder button_yes).

Ein manueller Eingriff ist in den meisten Fällen nicht notwendig. Falls doch erforderlich, kann eine manuelle Synchronisation über die folgenden Methoden passieren:

Tabelle 19-9: Manuell aufrufbare Datenmodellmethoden

Methode

Komponente

Funktion

:represent()

View

Die Daten aller gekoppelten Model-Attribute (.dataget) werden geholt und dem View-Objekt zugewiesen

:apply()

View

Für alle gekoppelten View-Attribute (.dataset) werden die Daten geholt und den Models zugewiesen

:propagate()

Model

Das Model-Objekt propagiert eine Änderung aller seiner Model-Attribute an die View-Objekte, die eine Kopplung aufweisen

:collect()

Model

Das Model-Objekt holt sich alle Daten aus den gekoppelten View-Objekten um sie seinen Model-Attributen zuzuweisen

Eine Synchronisierung findet nur zwischen Instanzen statt, niemals mit Default-Objekten oder Modellen.

Für eine optimierte Synchronisation von Teilwerten gibt es noch eine weitere Besonderheit. Wird eine Wertänderung signalisiert so wird der Index dieser Wertänderung weitergeleitet sodass nur dieser Einzelwert von der View-Komponente zu aktualisieren ist.

Beispiel

Über ein Timer-Objekt werden zufällige Farben ausgewählt und zufälligen Zellen einer Tabelle zugeordnet.

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;
  }
}

Bildschirmfoto dazu:

Abbildung 19-31: Zufällig gefärbte Tablefield-Zellen mit einem Timer als Datenmodell