Advanced programming


In this chapter you will learn everything about programming the user interface in iPlus. The following topics and questions are dealt with:

  1. How does the designer work and what tools are there?
  2. What are the main controls for presenting designs?
  3. How does data binding work?
  4. How do you convert data for presentation?
  5. Working with styles and setters.
  6. Dynamization using different trigger variants.
  7. Respond to events and user cations.
  8. Access to UI resources that are stored in the database.

 


You create the user interface with the  interface designer . You have the choice of creating the interface with the graphic tools or with the XAML editor. Changes in the graphical editor are synchronized when switching to the XAML editor and vice versa.

The tool window, with which you graphically edit the user interface, is divided into five sections:

 

Drawing tools (A)

You use the drawing tools to create shapes. After selecting a drawing tool, you can draw the shapes on the drawing area as you can with other graphics programs.

 

UI object tree (B)

Which objects or classes are displayed in the UI object tree always depends on the context.
If the designer is used in the development environment , the data context is always the class that was selected in the class tree of the development environment ( see Class Trees and Projects ). In the UI object tree, the root is therefore always the selected class (data context). Your child classes are shown below as a tree structure.

If the designer is opened during the runtime for the currently displayed business object, the data context is the class of the business object itself. In the UI object tree, the root is the class of the business object. It therefore makes no difference whether you go to the business object class in the iPlus project in the development environment and edit the design there because the root in the UI object tree is the same.

The business object for visualization is an exception: there, the data context is the entire application. Therefore, all application projects are displayed as root objects in the UI object tree.

Drag and drop a class from the UI object tree onto the drawing area. It is presented with the standard with the design that has been assigned to the "Control" category and with the "Standard design" ticked. If no check mark is placed, the first one with the lowest sorting index is used.

 

Property list (C)

This list shows the properties of the class selected in the UI object tree. Complex properties, which in turn have properties because they are a reference type, are also shown as a tree structure. This is particularly the case with one-entity objects. Example: A BOM item refers to a material. The material in turn on a unit. The unit has a name. The path to the name would be "CurrentBOMLine.Material.Unit.Name". 

If you drag and drop a property onto the drawing area, a suitable control element is created and the addressing (binding path) is set automatically. If a different control is to be used by default, you can set this in the "Controls" field in the "Properties" tab in the development environment.

 

Method list (D)

The methods of the class selected in the UI object tree are displayed in this list. 

If you drag and drop a method onto the drawing area, a suitable control element is created (button) and the addressing ( ACUrlCommand for method request ) is set automatically. If you want to use a different control element instead of a button by default, you can set this in the "Control element" field in the "Method" tab in the development environment.

 

List with texts and messages (E) 

This list shows texts and messages of the class selected in the UI object tree. 

If you drag and drop text onto the drawing area, a suitable control element is created that can display the text in the language of the logged in user.

 

Controls and drawings

The UI object tree contains two other root elements:

 

Switch to the XAML editor and look for which code has been generated:

 

  1. A Rectangle has been declared, which is a derivative of Shape.
  2. gip.core.layoutengine.VBVisual has been declared. VBVisual is a control that displays designs of a class that are assigned to the "Control" category. More on this in the next section.
  3. gip.core.layoutengine.VBTextBox has been declared. 
  4. A gip.core.layoutengine.VBButton  has been declared. 
  5. A gip.core.layoutengine.VBTranslationText has been declared.

All controls from the gip.core.layoutengine namespace have in common that they have the property "VBContent" , which is in the interface gip.core.datamodel.IACInteractiveObject declared. The purpose of VBContent is explained in the following section.

 


For designs you can

use.

So that the XAML parser can instantiate the controls, the namespace mapping must be specified in the root element using the xmlns attribute. Read more about this in the chapter "Integrating UI libraries".

In order for controls to appear in the designer tool window, the control must be announced with the ACClassInfo attribute class and assigned to the "TACVBControl" category:

 [ACClassInfo(Const.PackName_VarioSystem, "en{'VBBorder'}de{'VBBorder'}", Global.ACKinds.TACVBControl, Global.ACStorableTypes.Required, true, false)]
public class VBBorder : Border
{
}

In the tool window you will therefore mostly see controls from the iPlus library gip.core.layoutengine.dll that begin with the prefix "VB" . If it is derived from controls from the .NET framework , the endings are like the base class from .NET. eg VBtext block, VBTextBox, VBComboBox...

 

Drag a control onto the drawing area. Then switch to the XAML editor. The following code was generated:

 

Why should you use iPlus controls?

  1. iPlus control elements are so-called "custom controls" , whose look-and-feel is adapted to the iPlus system using ControlTemplates
  2. iPlus controls are integrated in the user group authorization system. The usage behavior and presentation of the control element (reading, changing ..) change according to the set rights. In addition, the usage rights of the control element can be influenced in the bound ACComponent.
  3. Labeling of data fields according to the language setting of the logged in user.
  4. Implicit binding via VBContent property . The user needs to have less knowledge about the different dependency properties of all control elements (e.g. text, content, IsChecked, SelectedDate, SelectedItem, ItemsSource, CommandBindings, ...) and how to do the data binding.
  5. Implicit context menu functions
  6. Navigation from bound entity objects to the responsible business object.
  7. Automatic instantiation, registration and deregistration of proxy ACComponents .
  8. Automatic binding to network-compatible properties .

 

 


Most iPlus WPF controls from "gip.core.layoutengine" implement these interfaces because of the advantages mentioned above (IVBContent is derived from IACInteractiveObject).

"string IACInteractiveObject.VBContent" is the most important property. VBContent typically includes an ACUrl that points, in relative or absolute terms, to an ACComponent instance, property, or sub-property of a complex type; Comparable to a PropertyPath that points to an entity object. In contrast to property paths, which are separated with dots, an ACUrl is separated with a backslash. Controls that implement IACInteractiveObject resolve this ACUrl when they are loaded for the first time (Loaded Event) by calling the "gip.core.datamodel.IACObject.ACUrlBinding()" method on the object which points to the IACInteractiveObject.ContextACObject property. Usually this is the encapsulated data context "FrameworkElement.DataContext", which is cast according to IACObject. The result of ACUrlBinding is a source and path variable, which are used to instantiate a binding and to set "Binding.Source" and "Binding.Path" automatically. The binding is then applied to the appropriate DependencyProperty via "SetBinding()" depending on the control element.

With a VBTextBox, for example, this would be the Text property.  For a VBDatePicker, for example, this would be the SelectedDate property.

 


In the screenshot of the XAML editor from the previous section you will find VBVisual elements. VBVisual is a ContentControl that also implements IVBContent. In contrast to the previously mentioned control elements, whose VBContent addresses a property, the VBContent of the VBVisuals addresses an ACComponent instance from the application tree , which in turn is set by DataBinding as a data context. After the data context has been set, the design of the corresponding class is displayed, which was assigned to the "Control" category and identified as "Standard Design" in the development environment. The loaded design in turn contains iPlus controls, the relatively specified of which can now be linked again via VBContent because the VBVisual has already set the correct data context.

Since several designs of the "Control" category  can be created for a class and only one of them can be the "standard design", you can use the "VBDesignName" property to specify the ACIdentifier of another design that is to be loaded instead.

 


VBDesign is a  ContentControl , which also implements IVBContent like VBVisual.

VBDesigns used to load and display styles of the category main (DUMain) and partial view (DULayout). Main views and partial views are required for business objects.When a business object is started, the iPlus framework first generates a root VB design and then loads the main view from the XAML parser . The main view is then assigned to the content property of  the root VB design and the data context is set with the new business object. Finally, the root VB design is placed in the logical tree attached so that it is visually visible.

According to the nesting principle of designs , it does not make sense to pack the entire layout (XAML code) in one main view. Instead, main views should load additional partial views (sub- designs) by declaring "<VBDesign>" elements in the XAML code and specifying the name (ACIdentifier) of the sub-design with a preceding asterisk "*" in the VBContent property:

e.g. <Grid>... 
<vb:VBDesign VBContent="*MyNameOfSubdesign"/>
...</Grid>

If no asterisk is prefixed , the VB content is interpreted as ACUrl and the path for a data binding is resolved. The property in the business object to be bound should be of type ACClassDesign. Thus, the business object can notify the VBDesign via PropertyChanged event that another design is to be loaded that is provided by the business object itself. With this technique you can implement e.g. a layout change at runtime in the style of Wizards .

If you place VBDesigns in the XAML code of partial views, you load additional partial views. Make sure that a partial view does not reload itself. There is no recursion check. Instead, a StackOverflow exception is thrown by the .NET framework.

When loading partial views, the data context is not changed , but is inherited from the root VBDesign via the logical tree. You change the data context yourself by declaring a binding to another property.

 

Child business objects

According to the  composition pattern , business objects can again have child business objects. Business objects are usually loaded just-in-time when they are needed. A child business object can also be instantiated via VBDesign and integrated into the design of the parent business object as a "plug-in". You can do this with the <VBInstanceInfo> element:

...
<vb:VBDesign VBContent="*Mainlayout">
<vb:VBInstanceInfo Key="BSOAlarmMessengerConfig_Child"
ACIdentifier="BSOAlarmMessengerConfig_Child"
SetAsDataContext="True"
SetAsBSOACComponet="True"
AutoStart="True">
</vb:VBInstanceInfo>
</vb:VBDesign
...

Several VBInstanceInfos can be declared within one VBDesign. 

In the ACIdentifier property, enter the name of the child business object that you previously added to the development tree in the class tree. It is best to enter the same name in the Key field (it is used to clearly identify the IntanceInfo instance in the logical tree). If the SetAsDataContext property is set to True, the data context of the VBDesign is set with the child business object. The AutoStart property specifies whether the child business object should be instantiated at runtime if it does not already exist.

Important : By changing the data context via SetAsDataContext, you also change the context for searching the design , which is specified in the VBContent property. In the example above, the design "main layout" is searched for by the child business object and not by the parent BSO in which the above XAML code is declared.

 

Special feature: BSOACComponent

If you were careful, you may have wondered how can the relative addressing of the child business object actually work in VBInstanceInfo if it is possible to change the data context by binding the design of the parent business object?

You are right, this does not work either and therefore the property BSOACComponent is declared in the VBDesign's base class VBDesignBase:

public static readonly DependencyProperty BSOACComponentProperty = 
ContentPropertyHandler.BSOACComponentProperty.AddOwner(
typeof(VBDesignBase),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(OnDepPropChanged))
);

Like the FrameworkElement.DataContext property, this property can be inherited in the logical tree. When loading from the root VBDesign, this property is also set and child business objects can then be addressed relatively - even if the data context is lost. For this reason, you should also set the "SetAsBSOACComponent" property to True in the VBInstanceInfo element, as you can see in the example above. 

 


VBDynamic

VBDynamic is a  ContentControl that implements IVBContent. The VBContent property should refer to a property that is of type string and that provides XAML code . Please avoid storing XAML code in the program code if possible. The XAML code should be loaded from the database or another data source if possible. VBDynamic is advantageous if layouts are generated using program logic or templates are manipulated. For example for graphs or the like.

<vb:VBDynamic VBContent="XAMLLayoutProperty" 
DataContextForContent="{vb:VBBinding VBContent=SelectedFunction}" />

 

VBDynamicContent

VBDynamicContent is a  ContentControl that implements IVBContent. It serves to present the value of a property bound by VBContent with a suitable design . It is comparable to the concept of Datatemplates and DataTemplateSelector in ".NET".

VBDynamicContent first analyzes the .NET type of the property. Using the .NET type, it searches for the corresponding iPlus type (ACClass). If the ACClass is found, the standard design of the category "Control" (DUControl) is searched. The standard design is loaded by the XAML parser and assigned to the content. The data context is set with the value of the bound property.

You can use this technique to dynamically display any type that you have announced by the ACClassInfo class of the iPlus runtime.

<vb:VBDynamicContent VBContent="CurrentParameterValue" />

 

 


To display data collections you need so-called ItemsControls. Data collections are then bound to the ItemsSource property so that the ItemsControl can list the data.

iPlus controls based on ItemsControls implement the interface gip.core.datamodel.IVBSource. The VBSource property is defined in IVBSource. VBSource is comparable to the VBContent property. The ACUrl specified there must refer to a data collection that is resolved using the "IACObject.ACUrlBindin ()" method so that a binding can be generated that is assigned to the ItemsSource property.

In the sample project, the two properties "SelectedInOrderPos" and "InOrderPosList" were declared in the business object BSOInOrder:

 

To display the "InOrderPosList" in a data grid , please use the iPlus control VBDataGrid, which implements IVBSource.

  1. Then enter "InOrderPosList" in the VBSource property so that an automatic binding to the ItemsSource property can be created in the background.
  2. Enter "SelectedInOrderPos" in the VBContent property so that an automatic binding to the SelectedItem property can be created in the background. 

 

 

The VBSource property does not have to be set. It is sufficient that you only specify VBContent. iPlus controls that implement IVBSource can automatically determine data collection using two different techniques:

 

ACPropertySelected and ACPropertyList

ACPropertySelected and ACPropertyList are attribute classes that are declared before properties so that they are known to the iPlus framework. In the source code above, the second parameter "string acGroup" is the same for both attribute classes (value "InOrderPos.ClassName"). This determined that the two properties belong together semantically and the data source can then be determined automatically when the "Selected property" is found.

 

Reference to data source in ACProperty attribute classes

Another variant is the use of the "string acSource" parameter in the various ACProperty attribute classes. The most important of these is the ACPropertyEntity attribute class, to make properties of EntityFramework classes known to the iPlus framework. For navigation properties (foreign keys), an ACUrl can then be specified in the acSource parameter, which the iPlus framework resolves during runtime and binds to the ItemsControl as a data source. 

Example:

[ACPropertyEntity(2, Material.ClassName, "en{'Material'}de{'Material'}", 
Const.ContextDatabase + "\\" + Material.ClassName, "", true)]

The yellow highlighted ACUrl addresses the property "public ObjectSet <Material>  Material " in the entity framework context class MyCompanyEntities from the sample project. This ACPropertyEntity declaration was made in the partial class InOrderPos . This describes that for the navigation property "Material" (foreign key "Guid MaterialID") in the table InOrderPos (order item) the data source can be found in "MyCompanyEntities.Material".

In the XAML code, the following declaration is sufficient without specifying VBSource:

<vb:VBComboBox VBContent="SelectedInOrderPos\Material" />

VBComboBox is another iPlus control that implements IVBSource. The ComboBox creates an automatic binding to its ItemsSource property by binding "ObjectSet <Material> MyCompanyEntities.Material" as a data source. When the ComboBox is opened, there is an automatic query to the database by querying the material table. The material selected in the combo box is then automatically assigned the "InOrderPos.Material" property because the SelectedItem property was bound in the background by the VBContent specification.

In fact, there is no direct access to "ObjectSet <Material> MyCompanyEntities.Material", but the database query class ACAccess <Material> is interposed, so that the query dialog can be opened with the F3 key to limit the search in the material table can. The query dialog requires a "storable query" suitable for the material type, which has been announced to the iPlus type system in the partial material class using ACQueryInfoPrimary .

 


VBContent and VBSource significantly simplify the use of iPlus controls. However, there are numerous other dependency properties that you would like to use via data binding. Or you use other third-party controls that you do not want to extend yourself with IVBContent and IVBSource. In these cases it would still be useful to be able to specify the binding source using ACUrl addressing.

The iPlus framework provides you with the class  "gip.core.layoutengine.VBBinding", which is derived from "System.Windows.Data.Binding". VBBinding has the property VBContent, to which you can assign an ACUrl string.

The ACUrl string can be specified relative to the current data context:

<vbv:VBMotor Width="20" Height="20" vbv:RunState="{vb:VBBinding vb:VBContent=RunState}" />

In this example, the design is loaded via VBVisual and the data context is set with an ACComponent that has the network-compatible property RunState. The ACUrl string in VBContent is therefore given relatively.

 

If you want to specify the ACUrl string relative to BSOACComponent, set the BindToBSO property to "true":

<vb:VBTextBox Text="{Binding Path=Gain}" 
ACCaptionTrans="{vb:VBBinding vb:BindToBSO=true, VBContent=\\Database\\ACProject(Variolibrary)\\ACClass(GIPControllerPIDData2006)\\ACClassProperty(Gain)\\ACCaption}" />

In this example, the Text property is bound to the "Gain" binding source, which belongs to an object that is the current data context. The ACCaptionTrans property is bound to a database ACUrl. In order for this to be resolved, an ACComponent or IACObject is required for which the "ACUrlBinding()" method can be called. Since the current data context is a primitive class that does not implement IACObject, BindToBSO is set to true, because then the ACUrlBinding method of BSOACComponent should be called in order to be able to resolve the binding source.

You can use VBBinding everywhere as a replacement for the classic .NET binding.