Screen scaffolding: controls

From OpenPetra Wiki
Jump to navigation Jump to search

Control Hierarchy

Root Control: Usually, the first Pagecontrl (tab), GroupBox (grp), User contrl (uco), or Panel (pnl). Sometimes, especially with inheritance of the forms, this does not work. So you can set the attribute RootControl=true for the control that you want to be the root (this behaviour is implemented in Ict.Tools.CodeGeneration.TCodeStorage.GetRootControl)

For Forms that are Dialogs (=these have OK, Cancel and Help buttons) and which use the value 'PetraFormDialog.yaml' for the 'BaseYaml' Element: all Controls need to be contained in a Panel called 'pnlDialogContent' and this needs to be the 'Root Control' [no need to set 'RootControl=true', though]).

Detail: if you have the word Detail in front of a control name, just after the control prefix, this means that the control belongs to the detail table.

grdDetails and pnlDetails are special controls which have special meaning for disabling the detail controls etc

Layout of Controls

Size of Controls

  • use Height=200 for setting the height (in pixels) of Controls.
    • this will work only on Controls whose height can be influenced - e.g. Panels, GroupBoxes, etc., but not e.g. on CheckBoxes, TextBoxes (unless it is multiline).
  • use Width=200 for setting the width (in pixels) of Controls.
    • this will work only on Controls whose width can be influenced - e.g. Panels, GroupBoxes, etc., but not e.g. on CheckBoxes.
  • use LabelWidth=100 for setting the width (in pixels) of the label that belongs to this control. This is useful to have same label width across several table layout panels.

It is possible to specify both Width and Height attributes, or just Height, but not Width alone!

  • use Stretch to make a control's width, height, or both, fill the enclosing control's width, height, or both.
    • 'Stretch=horizontally' makes a control's width fill the enclosing control's width
    • 'Stretch=vertically' makes a control's height fill the enclosing control's height
    • 'Stretch=fully' makes a control's height and width fill the enclosing control's height and width.
    • if the Control is arranged in a Grid (see below), the 'enclosing control' is substituted with the grid's 'cell' that the Control is placed in.
  • use Dock=Fill, or Dock=Top, or Dock=Bottom.
    • if you use a Dock attribute for each control in a container, then it would not use TableLayoutPanel, which might improve the behaviour on Mono (Mono does not cope well with TableLayoutPanel at the moment, Mono 2.4).
  • On a Panel (pnl) that hosts Button (btn) Controls the layout of the Buttons can be controlled automatically follows (the Buttons at the bottom of Dialog Forms use this feature!):
    • use AutoButtonMaxWidths=true to have the Width of all Buttons set to whatever is the widest of those Buttons. The placement of the Buttons (so that they are not overlapping after the Width change) is also done automatically.
    • use AutoButtonMaxWidthsAutoSizesContainerWidth=true in addition to 'AutoButtonMaxWidths' to have the Panel automatically resized so that all the Buttons fit on it after they have been resized.

Arranging Controls

  • TabIndex can control the tab order.
  • Padding and Margin both do the same thing. They take an x and y parameter which are relative adjustments to the default position of a control. The names are misnomers: they do not set the padding or margin properties of controls.
    • Example: Padding: 0, -7: Move the control up 7 pixels within its parent.
  • use Panels (pnl) or GroupBoxes (grp) to group controls.
    • Panels are invisible, whereas GroupBoxes draw a border around the Controls and have a title.
    • MarginLeft, MarginTop, MarginBottom, VerticalSpace and HorizontalSpace control the layout of controls within in Panel or GroupBox. The margins are the distance between the edges of the panel and the controls it contains; VerticalSpace and Horizontal space control the spacing between the controls. The default values are:
    MarginLeft: 5
    MarginTop: 7
    MarginBottom: 5
    VerticalSpace: 3
    HorizontalSpace: 5
  • by default, controls are arranged vertically (each control below the previous control)
    • to have the controls in one row (each control to the right of the previous control), use ControlsOrientation = horizontal
  • to control which panel's controls get initial focus, use TabIndex on the panel not on the controls.
  • to arrange controls in a Grid/Table style, use several RowX, RowY, etc as sub-elements of Controls; the elements of each row are arranged horizontally.
    • Tip #1: if you want a 'gap' between columns or rows (i.e. skip a colum or row), put the text 'Empty' in the place where a Control's name would go (this can be in a column or in a row). There needs to be a Control called 'Empty' so the Generator doesn't complain. (Any attributes set on this 'Empty' Control are ignored, since the Control doesn't get generated at all...)
      • if you have the need for several 'empties', name them 'Empty1', 'Empty2', etc. Also name the 'Controls' appropriately.
    • Tip #2: if you have the need to arrange Controls in a way that some Controls should go to a place in the TableLayout 'grid' that doesn't exist because of how the Columns are arranged, the simplest way of achieving this might be to place a Panel instead of the first of the Controls that should go on an 'irregular' position. Then arrange the Control(s) within that Panel. You can use the 'Margin' attribute to adjust the exact position of the Panel within the 'grid'. Example: pnlCheckBoxes in Ict\Petra\Client\lib\MPartner\UC_PartnerDetails_Organisation.yaml
    • Tip 3: The Width of the Columns of the Grid is determined automatically, as is the height of the Rows. There is a way to override the automatic width/height: use the ColWidths and ColHeight attributes. It is recommended not to use this feature too often, since the layout manager is quite good in assigning width depending on the contained controls.
      • Example 1: ColWidths: [0=Fixed:140, 1=Fixed:130, 2=Percent:20, 3=Fixed:80]: This assigns fixed widths (in pixels) to the first two and to the fourth column, and defines that Column 3 should take up 20 percent of the width of the whole grid.
      • Example 2: RowHeights: [2=Fixed:35]: This assigns a fixed height (in pixels) to the third Row; all other heights are determined automatically.
      • Example 3: The columns can either be including the label, or without the label. For example: Row0: [txtTest1, txtTest2] has two textboxes, plus the columns for the labels. So if you specify a width for column 0 and column 1, that will be split among the 4 columns. If you specify a value for column 0, 1, 2, 3, you will specify the width for the label columns too.
    • use Align=right to right-align a control in the grid's column that it is in.
      • By default, all controls are left-aligned, except for the Labels of controls that are auto-generated, those are right-aligned automatically.
    • use ColSpan=x to span a control over x Columns
    • use RowSpan=x to span a control over x Rows

For the TabOrder, the default is to go down each column, ie. Vertically. But you can also change the TabOrder to go per row, eg.:

Controls: {TabOrder=Horizontal}

(Automatic) Labels

  • Label sets the label for the control, otherwise it is built from the control name, without prefix
  • NoLabel=true will generate the control without a label
  • VariableLabelText=true will not add a translated label for the control, because the label will be set in Manualcode anyway

Other Attributes

  • ReadOnly=true will make a control read-only and also prevents the cursor from jumping into the control if the user 'tabs' through the screen with the <TAB> key.
    • Importantly, any data in that Control will also not get read out when data is written to the underlying DataRow if the Control is a data-bound Control!
  • Enabled=false will disable the control.
    • Alternatively, you can also put the name of a 'Condition' as the attribute value of the 'Enabled' Element (instead of true/false) - this way the Control will get enabled/disabled as the Condition gets enabled/disabled.
    • Alternatively, you can link a control with an Action, and enable/disable the Action depending on the state of the screen - the Control will then get enabled/disabled as the Action gets enabled/disabled.
  • Tooltip: You can specify a text that should appear on the Status Bar when the Control has the input Focus.
    • If there are default texts associated with a Control (e.g. for the 'New' Button) then setting the Tooltip property overrides that default text. That also applies to texts that are pulled out of petra.xml for data-bound Controls.

Different Sizes for Mono/other languages

Mono has quite some problems with the TableLayoutManager and AutoSize controls at the moment (Mono 2.4).

As well, for other languages the labels of controls might be longer, and we need different sizes for controls.

Therefore, you can create for each screen an inherited yaml file, and just define the height and width in pixels. eg, see Client/lib/MFinance/gui/UC_GLTransactions.en.yaml; you need to set the GUI language you want to compile for in the file.

Attributes for controls on report screens

  • ParameterName: will use the given name for the parameters that are sent to the server; otherwise it will be built from the control name
  • ParameterValue: for radio buttons, assign the value that should be set if this option is selected; otherwise it will be built from the control name, or from the OptionalValues list
  • NoParameter=true: will ignore the control, eg the ledger name text field is read-only, and is only for information
  • ClearIfSettingEmpty=true: this currently applies to date fields and auto populated comboboxes. If set to true it will empty screen values when settings are loaded and no setting can be found for those fields or the setting entry contains an empty value. If this attribute is not set and no settings value can be found then for date fields today's date will be displayed and auto populated comboboxes will be filled with the first available list entry.

Control Types

Container Controls


  • pnl: Panel. Container for any number of any Controls. Use this to logically group controls. Note: a Panel is not visible, unless a 'BackColour' is assigned.
    • One panel in particular is a special case - the pnlFilterAndFind. If you include this in your YAML you will get the special Filter/Find panel on your screen but you will need to code its elements in a particular way. Read more about the special Filter/Find panel here.
  • grp: GroupBox. Container for any number of any Controls. Similar to Panel, but it is visible: it draws a border around its containted controls and displays a title.
  • tab: Tab Control. Container for any number of TabPages (tpg). Cannot contain any other kind of Control!
    • DragTabPageEnabled: allow rearranging the order of TabPages (default: false)
    • ShowToolTips: allows showing of ToolTips on the headers of the TabPages (default: false)
    • if LoadPagesDynamically is true, the Generator creates code that dynamically loads a UserControl for TabPages that have 'LoadPageDynamically' set to true. That code is only executed when the TabPage is switched to for the first time. Using this facility, a programmer can improve the load time of a form that has many controls on many TabPages! (default=false)
  • tpg: TabPage of a Tab Control. Container for any number of any Controls. Similar to Panel, but has the appearance of a Tab and has a title.
    • ToolTip: defines ToolTip text that should be shown on the header of the TabPage. This is only shown if 'ShowToolTips' is set to true for the TabControl!
    • if LoadPageDynamically is true and 'LoadPagesDynamically' of the TabControl is true as well, the Generator creates code that dynamically loads a UserControl that is the only Control on this TabPage. DynamicControlType needs to be specified in this case. (default=false)
    • DynamicControlType specifies the UserControl that should get dynamically loaded. Only works if 'LoadPageDynamically' of the TabPage is true as well! See example for 'UserControl' for the value. Example:
           LoadPageDynamically: true
           DynamicControlType: Ict.Petra.Client.MCommon.TUCPartnerAddresses
  • uco: UserControl. UserControls can be understood as 'sub-forms' or simply parts of a screen whose layout is specified separately from the screen.
    • needs attribute 'Type' with the value containing the full namespace for the control, e.g.
           Type: Ict.Petra.Client.MPartner.Gui.TUC_PartnerEdit_PersonnelTabSet


  • spt: SplitContainer. Divides a part of the screen either horizontally or vertically and shows a 'Splitter line' between them. The user can 'drag' the 'Splitter line' with the mouse and give more or less space to controls on either side of the line.
    • SplitterOrientation. Supported values are: 'vertical', 'horizontal'.
    • SplitterDistance specified the Width or Height of the first Panel in pixels.
    • Panel1 and Panel2 refer to one control only at the moment.
  • rgr: RadioButton group. A GroupBox or a Panel that can contain several RadioButtons.
    • By default, a RadioButton Group is rendered as a GroupBox. To have it rendered as a Panel, set Element BorderVisible to 'false'.
      • If 'BorderVisible' is set to 'false', then by default this Panel has no Label; if you want it to have a Label, a Label Element needs to be specified. The Label will be displayed in the Column of the Layout Grid that precedes the Column in which the rgr Control is found (this is analogous to other data entry controls, e.g. TextBox).
    • The RadioButtons can be specified in one of two ways:
      • 1) Have 1..n values in the OptionalValues Element, separated by commas: this will create RadioButtons Controls in this Panel for each value.
        • By default, the first value in 'OptionalValues' is the 'active' RadioButton. To make a different value the 'active' RadioButton, prepend its text with the equals sign ('=').
        • If the RadioButton group is to be data bound and the DB Column that it is bound to may have NULL values, and in that case you want to have no RadioButton 'active', add the Element NoDefaultValue and set its value to 'true'. If this isn't done, the RadioButton that is specified as the 'active' one will be set to active, even if the DB Column has got a NULL value.
        • If you want to define the labels for the OptionalValues, add another list called LabelsForOptionalValues. This is used for the localised build as well.
        • The value of the radiobuttongroup might be stored to a string. To use a set of constants, use the list OptionalValuesConstants. Eg: OptionalValuesConstants: [MFinanceConstants.GIFT_TYPE_GIFT,MFinanceConstants.GIFT_TYPE_GIFT_IN_KIND,MFinanceConstants.GIFT_TYPE_OTHER]
      • 2) Put RadioButton Controls in the Controls Element list: this will create RadioButton Controls in this Panel for each of the RadioButton Controls. The advantage of doing it this way is that more of the RadioButtons' Properties can be influenced than with the 'OptionalValues' way, and that a RadioButton's Controls list can be populated (see next bullet point).
        • If a RadioButton's Controls Element is populated, then the Control(s) in there is/are Enabled/Disabled automatically: the Control(s) whose RadioButton is 'active' within the RadioButton group is/are automatically enabled, all other Controls specified in the other RadioButton's Controls Element(s) get automatically disabled!
    • for Reports only
      • ParameterValue can be specified for each RadioButton. This sets a unique value that is independent of the Label of the RadioButton (therefore it is also translation independent!)
    • Examples:
# Using OptionalValues Element
    ControlsOrientation: horizontal
    OptionalValues: [Posted, =Editing, All]
# Using Controls Element
    Controls: [rbtAllPartners, rbtExtract]
    ParameterValue: AllPartner
    Controls: [txtExtract]
    ParameterValue: Extract
# Using BorderVisible = false
    OptionalValues: ["SHORT FORM", "LONG FORM"]
    Label: Form Type
    BorderVisible: false
    ControlsOrientation: horizontal
  • rng: Range. Used for entering two values that define a range.
    • this is basically a special Panel.

Basic Controls

Edit Controls

  • txt: TextBox. A normal edit field (but see 'Format' and 'Type' below for different behaviours). NB Please be aware that the parser allows a ; (semicolon) inside the braces { } to separate properties. This needs to be fixed!
    • use TextAlign to align text in the TextBox. Supported values are: Left, Right, Center (default=Left).
    • use CharacterCasing to make the text typed appear in a certain character casing. Supported values are: 'Upper' (for all-uppercase), 'Lower' (for all-lowercase), 'Normal' (for showing the text as typed). Default=Normal.
    • use PasswordEntry=true to prevent any characters that are typed from being shown and show a mask symbol instead of the characters (default=false).
    • use Multiline=true to allow text entry in more than one line of text. To determine the height of the TextBox, use 'Height'. Make sure you assign 'Height', otherwise the TextBox will still appear in its default height, which makes it appear single-line (default=false).
      • if 'Multiline' is true, use ScrollBars to determine which scrollbars should appear. Supported values are: 'Horizontal', 'Vertical', 'Both', 'None' (default=none).
      • if 'Multiline' is true, use WordWrap=false to automatically scroll horizontally when the user types past the right edge of the control (default=true).
    • use DefaultValue to assign an initial text that is to be displayed in a TextBox.
      • this is ignored if the 'Format' Element is specified.
      • if the 'Type' Element is specified and it is set to 'PartnerKey' then only numeric values can be passed in via DefaultValue.
      • the passed-in text will be overwritten by an actual value from a DataRow's Column once the auto-generated code runs that data-binds the TextBox to a DataColumn of a DataTable (this obviously only happens for TextBoxes that are data-bound). Therefore DefaultValue is generally more suited for TextBoxes that are not data-bound.
    • use Format to restrict the characters that can be entered and to turn on specific formatting of the content
      • Supported values are: 'Integer', 'LongInteger', 'PercentInteger', 'Decimal', 'PercentDecimal', 'Currency'.
        • 'Integer' restricts the data entry to numbers (positive and negative) without decimals. No special formatting is done, except if 'PercentInteger' is used instead of 'Integer'; in this case a percent sign ( % ) is added to the number and it can also be entered by the user. The value of the number isn't changed through that.
        • 'Decimal' and 'Currency' restrict the data entry to numbers (positive and negative) with two decimals. To change the number of decimals, use the format 'Decimal(x)' or 'Currency(x)', where x is the number of decimals that should be allowed.
          • 'Decimal' formats the number with a decimal point and thousands separators. If 'PercentDecimal' is used instead of 'Decimal', a percent sign ( % ) is added to the number and it can also be entered by the user. The value of the number isn't changed through that. 'PercentDecimal' can also be used like this 'PercentDecimal(x)' to specify the number of decimals that should be allowed. 'Decimal' must not be used for amounts of money since it uses the international number formatting rules.
          • 'Currency' formats the number with a decimal point and thousands separators, and shows a Currency Symbol as a Label next to the TextBox. This is by default '###' and needs to be changed in the ManualCode.cs file by setting the 'CurrencyCode' Property of the Control. 'Currency' must only and always be used for amounts of money because it uses the international rules for currency formatting.
            • The number of Decimals of a Currency and the name of a Currency are automatically retrieved from the Cacheable DataTable 'CurrencyCodeList' after assigning a 'CurrencySymbol'. The Control adjust its Decimals Property according to the Decimals found in the Format of the Currency and sets up a ToolTip on the Currency Label to show the name of the Currency.
            • If the screen design requires that the currency label is always hidden, set the 'AlwaysHideLabel' attribute to true.
        • Please see Decimal And Currency Formats and International Settings for more information about displaying numbers and currencies in the user's preferred culture.
      • Should the user be prevented from leaving a number-only-TextBox empty, set the 'NullValueAllowed' attribute to 'false'. In that case the Control will default to '0' (Integer) or '0.00' (Decimal or Currency) when the user empties the Control and moves the Cursor to another Control. Default=true.
    • use Type to turn on a special layout and behaviour: If a supported value is assigned, the TextBox gets a 'Find' button to its left and a label to the right. The Find Button launches a find screen to look up valid values (or to look up Partners, in case of 'PartnerKey') and the label shows the description of the value (or the 'ShortName' of a Partner in case of 'PartnerKey'). Supported Values are: 'PartnerKey', 'Extract', 'Occupation', 'Conference'. More values can be added; contact us if you need more lookups and we can tell you how to add them.
  • chk: CheckBox
    • use CheckBoxAttachedLabel to optionally have a Label directly attached to the CheckBox. This Label can be displayed left or right of the CheckBox Control. The value of 'CheckBoxAttachedLabel' can be 'right' or 'left', depending on which side of the CheckBox the Label should appear.
      • This is not to be confused with the Label that is automatically generated for e.g. TextBoxes and CheckBoxes which is placed in the preceding 'column' of the generated layout. The directly attached Label goes into the same 'colum' as the CheckBox!
    • A CheckBox can have a list of dependent other controls in an optional 'Controls' list. Those Controls get enabled when the tick mark is displayed in the CheckBox and disabled if the tick mark isn't displayed.
  • nud: Numeric Up/Down
    • has a second label LabelUnit, which can be optionally set
    • use PositiveValueActivates to enable a condition when a positive value is selected
  • rbt: simple RadioButton
    • see also: RadioButton group
  • cmb: ComboBox (DropDown). A TextBox with a button that opens a list underneath from which values can be chosen. (Usually uses our custom control Ict.Common.Controls.TCmbAutoComplete.)
    • see also Overview Comboboxes
    • attribute Text gets or sets the text in the editable part of the ComboBox.
    • attribute OptionalValues defines the values of the combobox; prepend the default option with equals sign
      • sample: OptionalValues: [=Days, Weeks, Months]
    • attribute List: this will load the values from the server (and use a cache as well); it will use cmbAutoPopulatedComboBox instead of TCmbAutoComplete. Usually a label is displayed right of the ComboBox that shows the description of the value that the user has chosen (what content is shown in that Label depends on the 'List' value).
      • possible values for 'List': for a full list please check file \csharp\ICT\Petra\Client\CommonControls\Gui\cmbAutoPopulatedComboBox.cs, Enum 'TListTableEnum'.
        • Example: cmbCurrency: {Label=&Currency, DataField=AApSupplier.CurrencyCode, List=CurrencyCodeList}
      • attribute ComboBoxWidth in combination with 'List' allows to set the Width of the ComboBox alone ('Width' affects the combination of the ComboBox and the Label, not just the width of the ComboBox) and independent from the width of the first column (the width of the first column depends on the 'List' value). NOTE this value may be overridden in the case of auto-populated combos, if ComboBoxWidth is not wide enough when AppearanceSetup() is called.
      • use AllowDbNull to include a first row in the combo list that has a value of DbNull
      • use NullValueDesciption to set the description of the null value row (if being used). Default is 'Undefined'
    • attribute AutoComplete: this will store the entered search strings in the user defaults
      • cmbSupplierCode: {Label=S&earch Supplier, AutoComplete=SupplierSearchHistory, Tooltip=Search by supplier name or partner key}
    • attribute: MultiColumn: this will generate a TCmbVersatile combobox with several columns; make sure to set the column width of the second or more columns, otherwise they will not be visible! (not used yet anywhere)
    • Tip: Method 'GetSelectedItemsDataRow' returns the DataRow that underlies the currently selected ComboBox Item.

Other Controls

  • lbl: Label. Displays text. Please note that Labels are automatically generated for TextBoxes and many other Controls, unless the Element NoLabel with value 'true' is specified for that Control.
    • use Label to specify the text the Label should show. A colon (':') is automatically appended.
    • use Text to specify the text the Label should show. The text is shown as it is, no colon is automatically appended.
  • llb: LinkLabel. Displays a 'hyperlink-like' text (blue and underlined) that the user can click/activate.
    • use Label to specify the text the Label should show.
    • use Action to specify the Action that should be executed when the LinkLabel is clicked/activated.
      • Example: actLinkLabelTest: {Label=Link Label Test, ActionClick=LinkLabelTest}
  • btn: Button.
    • use Action to specify the Action that should be executed when the Button is clicked/activated.
    • use AcceptButton with value 'true' to make the Button the default button of a Form. The effect of doing this is that the Button gets 'clicked' when the user presses the <ENTER> key, no matter what Control has got the Focus when the user does this. Also, the Button appearance will be somewhat different from other Buttons so the user can tell that the Button is the default Button for the Form.
      • Example: btnNew: {AcceptButton=true}
    • if the button is called btnDelete there is an additional attribute that you can use
      • HandleEnableInManualCode=true will cause the auto-generator to not include the code that would enable/disable the delete button. If you manage the enabling of the button in ShowDetailsManual() you will need to set this attribute. see also Adding Delete Functionality to a Screen or Control
  • dtp: date picker. see TtxtPetraDate specification and testing

Advanced Controls

grd: Grid control

  • for more detail, see SourceGrid specification and testing
  • see here for information about autogenerated code for grid filter/find
  • the control needs to have the special name "grdDetails" for Master/Detail scenarios.
  • property SortOrder defines which column should be sorted. Several columns can be separated by commas; it is necessary to add DESC or ASC; example: SortOrder: ABatch.BatchNumber DESC
  • property SortableHeaders: if set to 'false' then the user will not be able to sort the Grid by clicking on the Column Headers. (By default the user can sort the Grid by clicking on the Column Headers.)
  • property EnableMultiSelection: if set to 'false' then the user will not be able to select/highlight multiple Rows at once. (By default the user can select/highlight multiple Rows at once.)
  • property RowFilter enables grid to be filtered by certain column values. Several columns can be separated by commas; it is necessary to have a member variable defined in the ManualCode file where the value for each filtered column is set; example: RowFilter: ATransAnalAttrib.BatchNumber (this needs to have private Int32 FBatchNumber defined in the ManualCode file).
  • property TableName makes the list in Columns shorter.
  • property Columns lists the columns to be displayed.
  • property CustomColumns: allows custom column title or custom format to be specified (the 'CustomColumns' property needs to be on the same indent level as the 'Columns' property).
    • property Label needs to be specified if a column title should be displayed. If this isn't done an empty label is assumed and as a result the column title in the Grid will not display any text for this Column.
    • property Type is optional.
      • Type 'Boolean' is displayed as a disabled CheckBox.
      • Type 'Boolean(MyTrueText,MyFalseText)' displays not true or false, but the text given as parameter. This is used for example with the DebitCreditIndicator in GL transactions grid.
      • Type 'DateTime' is displayed in the openPETRA international date format (eg. 01-DEC-2010).
      • Type 'ShortTime' shows a time value in localised short string format (eg. HH:MM).
      • Type 'LongTime' shows a time value in localised long string format (eg. HH:MM:SS).
      • Type 'Currency' displays data formatted as numbers (positive and negative). By default the numbers are displayed with two decimal fractions and use the current international currency format. To change the number of decimal fractions, use the format 'Currency(x)', where x is the number of decimal fractions that should be displayed. Negative numbers are displayed using a red text colour. Currency types are displayed right-aligned. In order to get the correct decimal and thousands separators for the text you must use Currency type for amounts of money. Use Decimal type for other non-money quantities.
      • Type 'Decimal' displays data formatted as numbers (positive and negative). By default the numbers are displayed with two decimal fractions and use the current international decimal format. To change the number of decimal fractions, use the format 'Decimal(x)', where x is the number of decimal fractions that should be displayed. Decimal types are displayed right-aligned. In order to get the correct decimal and thousands separators for the text you must use Decimal type for non-money quantities. For example use Decimal(10) type when the data is an exchange rate or Decimal(1) for an inflation percent.
      • Type 'PartnerKey' is displayed in the openPETRA standard partner key format (10 digits with leading zeros, e.g. 0038044374).
    • Cumulative Example:
    Tagged: {Type=Boolean}
    DateDue: {Label=Date Due, Type=DateTime}
    DetailRateOfExchange: {Label=Rate of Exchange, Type=Decimal(10)}
    DetailTransactionAmount: {Type=Currency}
  • property ColumnWidth is optional.
    • You can define the width for named columns. eg. ColumnWidth: {NumberOnPaperStatement=40, AccountName=100, DateEffective=100, TransactionAmount=100}
    • per default, the column width is auto sized depending on the content of the cells.
  • property MaxAutoSizeRows is optional
    • for autosizing the column width, the first number of rows are considered to calculate the width of the columns.
    • if it is not defined, then it defaults to 10 rows.
Grid Events
  • attribute ActionEnterKeyPressed points to a function that is called if the user presses <Enter> while a grid has focus (normally the same function as for DoubleClick).
    • sample: grdSupplierResult: {Dock=Fill, ActionDoubleClick=actSupplierTransactions, ActionEnterKeyPressed=actSupplierTransactions}
  • attribute ActionDoubleClick points to a function that is called when the user double-clicks on a grid row.
    • sample: grdSupplierResult: {Dock=Fill, ActionDoubleClick=actSupplierTransactions, ActionEnterKeyPressed=actSupplierTransactions}
  • attribute ActionFocusRow points to a function that is called when the selection of the current row changes.
    • This setting is now ignored by the YAML parser if the grid name is grdDetails. See Grid Events for details!

trv: TreeView



  • ppv: PrintPreview. This is currently only used internally, by the PrintPreviewWithToolbar
  • pre: PrintPreview With Toolbar: this is used with the windowBrowsePrint template. a toolbar is added with current page, number of all pages, buttons for previous and next page, and print current page and general print button.


  • tbb: ToolBar Button
  • tbl: ToolBar Label
  • ttx: ToolBar TextBox
  • cmb: ToolBar ComboBox
    • Width specifies the width of the ComboBox in pixels.

Data Binding

We don't use .Net databinding, but the generator wires the data.

  • You can use the attributes MasterTable and DetailTable that will try to match each control to the field in the table with the same name (detail fields must be called <prefix>Detail<fieldname>, eg. txtDetailAmount)
  • You can specifically bind data with DataField, either with the data table name or just the field name.
    • sample: DataField=AApSupplier.CurrencyCode
  • For some controls, eg radiobuttons used for filtering the displayed data, you need to avoid that the Save button gets activated: use SuppressChangeDetection: true

special lookups

  • PartnerShortNameLookup: this is for printing the partner short name on a screen; usually this is read-only; but you need to specify that with ReadOnly=true
    • sample: txtSupplierName: {Label=Current Supplier, ReadOnly=true, PartnerShortNameLookup=AApDocument.PartnerKey}

special behaviour

  • if you link a boolean database field to a combobox with 2 values, it will match the value (first value is false, second value is true).
    • sample:
      OptionalValues: [=Invoice, Credit Note]
      DataField: CreditNoteFlag


  • attribute OnChange points to a function that is called if the value in the control changes
    • sample: dtpDateIssued: {Label=&Date Issued, OnChange=UpdateCreditTerms}
    • This applies the same to all kinds of Controls, although the Events of various Controls which denote a 'change' are indeed different. The Generator hooks up the following Events for you when the attribute OnChange is used:
      • For all Controls other than the ones listed below: the 'ValueChanged' Event is hooked up.
      • TextBox: the 'TextChanged' Event is hooked up.
        • This Event is fired while typing! (If you want an Event that is fired after all characters have been typed, use OnLeave.)
      • ComboBox/DropDown: the 'SelectedValueChanged' Event is hooked up.
      • CheckBox and RadioButton: the 'CheckedChanged' Event is hooked up.
      • DateTimePicker: the 'DateChanged' is hooked up.
  • attribute OnEnter points to a function that is called when a Control is entered
    • example: txtPassportName: {OnEnter=SuggestPassportName}
    • This applies the same to all kinds of Controls that can receive focus
    • OnEnter is executed no matter how the Control is entered (e.g. by using the <Tab> key, using the mouse, or by keyboard shortcut)
    • OnEnter is only called when the control is entered whereas GotFocus is called every time the user e.g. clicks on the control
  • attribute OnLeave points to a function that is called once a Control is left
    • sample: txtDetailTimeZoneMinimum: {Label=Time Zone From, OnLeave=UpdateTimeZoneMaximum}
    • This applies the same to all kinds of Controls
    • OnLeave is executed no matter how the Control is left (e.g. by using the <Tab> key, using the mouse, or by keyboard shortcut) - with one exception: it is not executed if a user clicks on a ToolBarButton!
  • attribute Action points to an action that is executed for Click etc
    • actually, there is now a convention, ie. the name of the control matches the name of the action, and the sample would not be even necessary
    • sample: mniNewSupplier: {Action=actNewSupplier}
  • attribute ActionClick/ActionDoubleClick points to a function that is called if the control is clicked
    • example: grdSupplierResult: {Dock=Fill, ActionDoubleClick=actSupplierTransactions}
  • attribute ActionOpenScreen will open a screen (defined with full namespace); if PropertyForSubScreens is set for the form, and the new screen has that propery too, it will be assigned
    • example: mniAccountsPayable: {Label=&Accounts Payable, ActionOpenScreen=Ict.Petra.Client.MFinance.Gui.AccountsPayable.TFrmAPMain}
  • Events specific to a Grid: see Grid Events