Lade...
 

ImportContext

ImportContext

ImportContext(name, bind(variableconsumer~variableprovider , . . .))

Für das Statement Import kann optional ein Context angegeben werden. Die Anweisung definiert eine Variablenbindung und einen eigenen Widget-Namensraum. Eine Einführung zum Thema Widget Provider finden Sie hier.

Das ImportContext-Statement darf in einem Modul auf der gleichen Ebene definiert werden, wie Fenster (also nicht innerhalb einer Aktionsliste). Ein Import-Context gilt immer für das gesamte Modul und wird von Basismodule auch an abgeleitete Module vererbt, sodass der Import-Context des Basismoduls dort direkt wiederverwendet werden kann.

230899 darf es mehrere ImportContext-Statements für den gleichen Bezeichner geben. Das letzte Statement definiert dann die für diesen Import-Context gültige Definition. Es ist auch erlaubt, den Import-Context eines Basismoduls auf diese Weise zu überschreiben. 
Beim Überschreiben eines Import-Contexts darf die Variablenbindung geänert werde, die Provider-Bindung wird durch die Überschreibung jedoch nicht zurückgesetzt. Der Import-Context darf also nicht für einen anderen Provider verwendet werden, nachdem er überschreiben wurde.
Das ImportContext-Statement darf nun auch als Kind-Element innerhalb von Fenster-Definitionen stehen, obwohl der Import-Context kein Widget ist. Dies erlaubt jedoch die Definition des Import-Contexts an genau der Stelle, an welcher er auch benötigt wird und führt so zu besser lesbarem Code.
Bsp:

Window(BaseData, ACCEPT_DROP, 0, 0, 0, 0, T("Stammdaten", "Base data")) { Composite(SingleGrp, 0, 0, 100, 150) { Notebook(SingleNoteBook, 0, 0, 0, 0) { // --------------------------------------------------------------------------------- Window(SingleAddressWin, 0, 0, 0, 0, T("Adresse", "Adresse")) { ImportContext(Address, bind(addressObject~addressObject, partner~addressOwner)) Import(SingleAddressGroup, cxAddress::EditWin.SingleAddressGroup, 5, 2, 500, 180, Address) Attach(SingleAddressGroup, RIGHT, STRETCH, 5) Attach(SingleAddressGroup, BOTTOM, STRETCH, 2) } ...

 

 

Falls einem Import-Statement kein Import-Context zugewiesen wird, dann wird ein implizit definierter Kontext zugewiesen (1 Context pro (Provider,Consumer)-Tupel).

Wichtig: Ein Import-Context kann immer nur mit einem Provider verbunden werden. Es ist nicht erlaubt, Widgets aus unterschiedlichen Providern im gleichen ImportContext zu importieren.

Parameter
Parameter   Beschreibung Details
name * ein Identifikator als Name (1)
bind(Variablenliste)   beschreibt die Variablenbindung (2)

 

1. Der Name verbindet ein Import Satement mit dem Context.

2. Die Variablenliste verbindet im Consumer-Modul definierte Variable mit im Provider-Modul definierten Variablen.
    Sobald Code der importierten Widgets ausgeführt wird, hat die Variable des Providers den gleichen Wert wie die des Consumer-Moduls.
    Wird dabei der Wert verändert, ist der neue Wert auch im Consumer-Modul sichtbar.

    Wenn beide Namen übereinstimmen, kann kurz bind( . . ., variableconsumer_provider, . . .) geschrieben werden.

Vor Dll-Version: 230555 
Jede Variable eines Consumers darf nur an maximal eine Variable eines Providers gebunden werden. Und jede Variable des Providers darf nur an maximal eine Variable des Consumers gebunden werden.

230555 ist es erlaubt, mehrere Variablen aus dem Provider an eine Variable aus dem Consumer-Modul zu binden. Es ist aber weiterhin nicht erlaubt, eine Provider-Variable and mehrere Consumer-Variablen zu binden.

Trennung der Widget-Namesräume

Eines der Grundkonzepte des Widget-Provdings ist es, dass die importierten Provider-Widgets von den Consumer-Widgets möglichst entkoppelt sind und sich folgerichtig auch nicht ungewollt gegenseitig beeinflussen. Dadurch soll gewährleistet sein, dass Widgets an allen Stellen importiert werden können, ohne das Zielfenster dahingehend anpassen zu müssen.

Der eigene Widget-Namesraum des Import-Contexts ist ein Kernkonzept dieser Entkopplung, denn Widgetbefehle finden nur Widgets (by-name) aus dem eigenen Import-Context. Falls im Consumer-Modul also zufällig ein Widget genauso heißt, wie im importierten Provider-Widget, dann ist damit sichergestellt, dass sich Widgetbefehle nicht zufälliger Weise auf das falsche Widget beziehen. Dies ist insbesondere dann wichtig, falls das gleiche Widget mit unterschiedlichen Kontexten mehrfach in das gleiche Fenster importiert wird.

Da Import-Statements ohne Angabe eines Import-Context einen Default-Context erhalten, der pro Provider definiert ist, folgt daraus, dass sich alle aus dem gleichen Provider importierten Widgets (ohne Import-Context-Angabe) gegenseitig finden können, während sich Widgets aus unterschiedlichen Providern nicht finden können.

Da ein Import-Context nur an einen Provider gebunden werden kann, werden dadurch auch die aus unterschiedlichen Providern importierten Widgets gegeneinander abgeschottet.

Ausnahme: by-object STACK-Parameter

230739
Falls in Widget-Befehlen das Einstiegsobjekt (windowID) als CX_WIDGET-Objekt auf dem Stack übergeben, dann werden die oben genannten Einschränkungen bei der Widget-Suche aufgehoben und Widgets aus unterschiedlichen Import-Contexten können sich gegenseitig by-name finden. Diese Sonderregel ist für die Sonderfälle implementiert, in denen entweder der Consumer besonders Wissen über die Struktur des importierten Widgets hat und dies nutzen will oder vice versa. 

Achtung: Dies ein solches Vorgehen erhöht die Kopplung zwischen Consumer und Provider und erschwert die unabhängige Entwicklung beider Komponenten.

Funktionsweise des Variablenbindings

Das folgende Beispiel verdeutlicht, wie der Zugriff auf Variablen innerhalb von Modulen grundsätzlich funktioniert. Jedes Modul hat ein eigenes Scope, in welchem die Variablen existieren und jedes Modul kann nur auf die Variablen aus dem eigenen Scope zugreifen.

Var Binding No Binding

 

Mit dem Variablenbinding kann nun eine Umleitung für die Auflösung von Variablen definiert werden. Diese Umleitung ist immer dann aktiv, wenn der entsprechende ImportContext aktiv ist, also wenn das importierte Widget eine Message verarbeitet.

Hierbei ist es wichtig sich klar zu machen, dass das Binding nur eine Umleitung (blau markiert) auf eine Variable aus einem anderen Scope definiert. Die umgeleiteten Variablen aus dem Provider (rot markiert) existieren weiterhin, sind aber (während das Binding aktiv ist) einfach nicht erreichbar.

Das Binding überschreibt keine Variablen und führt keine Synchronisierung durch. Die Scopes der beiden Module werden durch das Binding nicht beeinflusst. Das Binding beeinflusst lediglich die Suche der Variablen beim Lese- & Schreibzugriff.

Var Binding With Binding

Die Abbildung veranschaulicht auch gut, wieso es möglich ist, mehrere Provider-Variablen an die gleiche Consumer-Variable zu binden, aber nicht eine Provider-Variable an mehrere Consumer-Variablen (der Zugriff wäre nicht mehr eindeutig).