Erweiterte Programmierung


Die nachfolgenden Übungen werden in der Visualisierung gemacht.

Die Visualisierung ist eine Klasse wie jede andere auch (Ventil, Motor, Mailkomponente, Artikelverwaltung...). Designs für eine Visualisierung können daher in der Entwicklungsumgebung bei der Klasse BSOVisualisationStudio hinzugefügt und editiert werden (mit dem Verwendungstyp bzw. Kategorie "Visualisation"). In der Regel öffnet man aber das Programm per Menü und fügt neue Designs mit dem Symbol  hinzu. Der Effekt ist derselbe.

Sie können daher die Design-Übungen entweder bei Ihrer Übungsklasse in der Entwicklungsumgebung durchführen oder eben in der Visualisierung. Der einzigste Unterschied ist, dass der Datenkontext im ersten Fall Ihre Übungsklasse ist und im zweiten Fall die Visualisierung selbst. Das bedeutet, dass die Adressierung von Eigenschaften unterschiedlich ist. Bei der Übungsklasse wird relativ adressiert und in der Visualisierung absolut.

Noch ein Tipp:

Erstellen Sie zuerst Ihre Anwendung (Modell) und starten Sie die Anwendung als Server (im iPlus-Demoprojekt ist es der 00-Benutzer). Dann können Sie per Komponentenexplorer Eigenschaftswerte ändern und so die dynamischen GUI-Änderungen sofort sehen bzw. testen, die sie in den Übungen programmiert haben.

 

Die einfachste Variante eine Abhängigkeitseigenschaft zu setzen, um die grafische Präsentation eines grafischen Elementes (UIElement) zu verändern, ist das "direkte Setzen". 

Im folgenden Beispiel wurde zuerst ein Rechteck gezeichnet, bei dem die Füllung verändert werden soll. Dazu Öffnen Sie das Eigenschaftsfenster und gehen zur Eigenschaft "Fill". Öffnen Sie das Farbfenster und wählen eine Farbe aus:

Schalten Sie auf die XAML-Registerkarte um. Im XAML-Code sehen Sie, dass die "Fill"-Eigenschaft direkt gesetzt wurde:

Die Fill-Eigenschaft ist vom Typ Brush was eine komplexe Klasse ist. Deswegen müsste normalerweise der Wert in der "Eigenschaftenelement-Syntax" beschrieben werden. Es reicht allerdings auch direkt den Farbwert "#FFE57575" zu schreiben, weil während des XAML-Parsevorgangs passende Typekonverter verwendet werden, die eine Umwandlung dieses Strings in eine Brushklasse automatisiert durchführen.


Möchte man allerdings den Farbwert, bzw. eine beliebige grafische Eigenschaft, abhängig vom Eigenschaftswert einer ACComponent machen, gibt es verschiedene Techniken.

Eine davon ist die Nutzung von Konvertern. Konverter sind Klassen, die die Schnittstelle IValueConverter implementieren. Sie haben die Aufgabe Werte von Quelleigenschaften (Modell, Source) in den Datentyp der Eigenschaft des WPF-Elementes (Target) zu konvertieren.

In unserem Beispiel von oben ist der Typ der "Fill"-Eigenschaft Brush. Wir möchten aber, dass sich die Farbe ändert, wenn sich ein Zustand der gebundenen AComponent-Instanz ändert. Konkret ist das die ACState-Eigenschaft der Klasse "gip.core.autocomponent.PABase". Der Typ dieser Eigenschaft ist jedoch  "gip.core.autocomponent.ACStateEnum". Weil Brush und ACStateEnum völlig unterschiedliche Typen sind benötigen wir eine Programmlogik, die eine Umwandlung durchführt. Hier gibt es zwei unterschiedliche Lösungsmöglichkeiten:

  1. Man erstellt eine Klasse, die IValueConverter implementiert und die gewünschte Logik in der Methode Convert ausprogrammiert.
  2. Man verwendet die eine passende Ableitung der Klasse "gip.core.layoutengine.ConverterBase". Die ConverterBase-Klasse hat die Funktionalität, dass Sie per ACUrlCommand eine beliebige clientseitige Methode aufrufen kann. Diese kann entweder hardcoded in einer Assembly sein oder eine clientseitige Skriptmethode.

Im nachfolgenden Beispiel wurde eine Skriptmethode definiert die "ACStateEnum" in "Brush" konvertiert:

 

Die Methode wurde bei der Klasse "Environment" definiert damit sie "global" von verwendet werden kann. (Skriptmethoden können natürlich auch direkt bei einer konkreten Klasse definiert werden, was der Regelfall ist.)

Im nächsten Schritt möchten wir die Skriptmethode verwenden. Dazu öffnen Sie das Werkzeugfenster und das Eigenschaftsfenster und ordnen sie sie nebeneinander an:

 

Navigieren Sie im Werkzeugfenster zu einer Instanz aus einem Anwendungsbaum (Projekt) und erweitern den "Properties"-Expander um die Eigenschaften zu sehen.

Ziehen Sie per Drag & Drop (1) die entsprechende Eigenschaft (Modell) auf die Fill-Eigenschaft des selektierten Rechteckes (UI-Element). Im Beispiel muss es die ACState-Eigenschaft sein, damit unsere Skriptmethode kompatibel ist.

Im nächsten Schritt selektieren Sie die Environment-Instanz, weil dort die Skriptmethode "ACStateBrush" deklariert wurde. Hier expandieren Sie den Methoden-Abschnitt und selektieren die "ACStateBrush"-Methode. Ziehen Sie anschießend die Methode per Drag & Drop (1) auf die Fill-Eigenschaft des selektierten Rechteckes (UI-Element):

 

Öffnen Sie nun bei der Fill-Eigenschaft die Unterfenster, damit Sie sehen was der Designer generiert hat. Durch Umschalten auf die XAML-Registerkarte sehen sie den entsprechenden XAML-Code:

 

Es wurde folgender Code generiert:

Fill="{vb:VBBinding 
Converter={vb:ConverterBrushSingle vb:ACUrlCommand=!ACStateBrush, vb:GlobalFunction=True},    
vb:VBContent=\\Mixery\\HopScale1\\Discharging\\ACState}"

ConverteBrushSingle ist eine Implementierung der abstrakten Klasse "gip.core.layoutengine.ConverterBase" weil Sie Brush als Rückgabewert hat. (Es gibt eine Vielzahl von Ableitungen für die gängigsten UI-DependencyProperties). Danach wird in ACUrlCommand der Methodenaufruf von ACStateBrush angegeben. Die Eigenschaft "GlobalFunction" wird immer automatisch gesetzt, wenn es sich um Methoden aus der Environment-Klasse handelt. Ansonsten wird GlobalFunction nicht benötigt, wenn der XAML-Code in einem Design ist, wo der Datenkontext die entsprechende Klasse selbst ist (Normalfall).

Sie müssen also immer wissen welches der aktuelle Datenkontext ist und dementsprechend müssen Sie den ACUrlCommand-String richtig (relativ oder absolut) angeben!

Der VBContent ist die ACUrl-Adresse zur ACState-Eigenschaft. (Wenn Sie das Design an der Funktionsklasse selbst definiern würden, dan wäre die Adresse relativ nur "ACState", weil der Datenkontext die Funktionsklasse selbst ist.)

Speichern Sie Ihre Änderungen und schließen den Designer. Öffnen Sie den Komponentenexplorer und testen Sie, ob sich die Farben ändern, wenn Sie die ACState-Eigenschaft ändern.

 

Wenn der Farbwert oder eine andere grafische Eigenschaft von mehr als einer ACComponent-Eigenschaft abhängt, benötigt man Multibindings.

Multibindings werden automatisch vom Designer generiert, sobald sie eine weitere Eigenschaft (Modell) per Drag & Drop auf die grafische Eigenschaft des selektierten grafischen Elementes ziehen. Im folgenden Beispiel ziehen Sie die SensorState-Eigenschaft der Emergency-ACComponent auf die Fill-Eigenschaft des selektierten Rechteckes (PropertyWindow)

 

Öffnen Sie nun bei der Fill-Eigenschaft die Unterfenster, damit Sie sehen was der Designer generiert hat. Durch Umschalten auf die XAML-Registerkarte sehen sie den entsprechenden XAML-Code:

 

 

Bitte bedenken Sie, dass Sie auch eine andere Methode bereitstellen müssen, die zwei Parameter besitzt, weil das Multibinding nun zwei Werte liefert. Diese neue Methode können Sie ebenfalls per Drag & Drop draufziehen, wie es im vorigen Abschnitt erklärt wurde. Im Beispiel oben lautet die Methode "ACStateBrush2Params".