Axaptapedia is now maintained by AgileCadence For more information please click here.

Difference between revisions of "Runtime form controls"

From Axaptapedia
Jump to: navigation, search
(Adding menu-item buttons)
Line 96: Line 96:
  
 
See [[Media:AJ_DynamicControls.xpo|this project]] for two forms demonstrating the above concepts.
 
See [[Media:AJ_DynamicControls.xpo|this project]] for two forms demonstrating the above concepts.
 +
 +
==Adding grid control==
 +
 +
In most cases you'd better use visible property of this control's type. But sometimes you have to add a grid on an existing form and without any opportunity of change. This example will help you. Rather you are making this modification on forms, that are managed  from class. In our tutorial case this is runable tutorial_AddRunTimeControls class. This following code adds a grid control of the selected table. You may find similar functionality in the form SysTableBrowser:
 +
 +
<xpp>
 +
void addRunTimeControls(FormRun _formRun)
 +
{
 +
    FormGridControl        formGrigControl;
 +
    Form                  _form;
 +
    FormBuildDataSource    formBuildDataSource;
 +
    FormBuildDesign        formBuildDesign;
 +
    FormBuildStringControl formBuildStringControl;
 +
    FormBuildGridControl  formBuildGridControl;
 +
    Object                formBuildControl;
 +
    FormBuildGroupControl  formGroupControl;
 +
    CustTable              custTable;
 +
    DictTable              dictTable;
 +
    TableId                tableID;
 +
    ;
 +
 +
    // Adding a Grid  control, this used in  SysTableBrowser
 +
    tableID    = picktable();
 +
    dictTable  = new DictTable(tableID);
 +
    _form = _formRun.form();
 +
    formBuildDataSource = _form.dataSource(2);
 +
    formBuildDataSource.name(dictTable.name());
 +
    formBuildDataSource.table(dictTable.id());
 +
    formBuildDataSource.autoQuery(true);
 +
    formBuildDesign = _form.design();
 +
    formBuildDesign.widthMode(-1);
 +
    formBuildDesign.widthValue(600);
 +
    formBuildDesign.heightMode(-1);
 +
    formBuildDesign.heightValue(400);
 +
 +
    formGroupControl = formBuildDesign.addControl(FormControlType::Group, 'SecondGrid');
 +
    formGroupControl.caption("Dynamic Grid");
 +
    formGroupControl.widthMode(1);
 +
    formGroupControl.heightMode(1);
 +
    formBuildGridControl = formGroupControl.addControl(FormControlType::GRID,'Grid');
 +
    formBuildGridControl.dataSource(dictTable.name());
 +
    formBuildGridControl.name('AddRunTime');
 +
 +
    formBuildGridControl.widthMode(1);
 +
    formBuildGridControl.heightMode(1);
 +
    this.showFields(tableNum(custTable), formBuildGridControl, formBuildDataSource);
 +
 +
    _formRun.controlMethodOverload(true);
 +
    _formRun.init();
 +
    _formRun.run();
 +
    _formRun.detach();
 +
}
 +
</xpp>
 +
 +
And define the fields on grid.
 +
 +
<xpp>
 +
public void showFields(tableId                tableId,
 +
                      FormBuildGridControl    formBuildGridControl,
 +
                      FormBuildDataSource    formBuildDataSource)
 +
 +
 +
{
 +
    FormBuildStringControl          formBuildStringControl;
 +
    DictTable                      dictTable;
 +
    fieldId                        fieldId;
 +
    int                            i;
 +
    int                            fieldCnt;
 +
    ;
 +
    dictTable  = new DictTable(tableId);
 +
    for (i=1; i<=3; i++)
 +
    {
 +
        fieldId = dictTable.fieldCnt2Id(i);
 +
        formBuildGridControl.addDataField(formBuildDataSource.id(), fieldId2Ext(fieldId, 1));
 +
    }
 +
}
 +
</xpp>
  
 
[[Category:Form development]]
 
[[Category:Form development]]

Revision as of 07:35, 8 February 2007

Creating runtime form controls can be useful in a variety of circumstances. Any type of control can be added at runtime: groups, string edits, buttons etc.

Standard Axapta uses this technique to dynamically add 'Action' buttons to forms when required. The code to add controls for these functions is called from the new() method of SysSetupFormRun.

Introduction

The basic process to add controls and intercept their events at runtime is as follows:

  • use form.addControl(ControlType, ControlName) to add the control
  • call form.controlMethodOverload(true) to enable over-riding of the control events
  • write appropriate event handler methods on the form


If you are dealing only with buttons, then it is possible to set the MenuItemType and MenuItemName on the button when it is created. In this way, you can directly call a report, class or another form, and you don't need to write additional code on the form to deal with the button click.

The Basics

The simplest example uses the init() method of a form to add the controls, and design-time methods to intercept the control events. Take note of the control names used during the .addControl() call. In the example below, the control names are 'DynamicStringControl' and 'DynamicButtonControl'.

<xpp>

public void init()
{
    FormStringControl   formStringControl;
    FormButtonControl   formButtonControl;
    FormGroupControl    formGroupControl;
    ;

    // Adding a group
    formGroupControl = this.form().addControl(FormControlType::Group, "MyGroup");
    formGroupControl.caption("It's my group!");

    // Adding a string to a group
    formStringControl = formGroupControl.addControl(FormControlType::String, "DynamicStringControl");
    formStringControl.label("Dynamic string control");

    // Adding another string to the group using the same name.  This will use the same event method as the
    // first "DynamicStringControl"
    formStringControl = formGroupControl.addControl(FormControlType::String, "DynamicStringControl");
    formStringControl.label("Dynamic string control2");

    formButtonControl = this.form().addControl(FormControlType::Button, "DynamicButtonControl");
    formButtonControl.text("Dynamic button");

    this.controlMethodOverload(true);

    super();
}

</xpp>

You can then write event handler methods for the controls at the top (element) level of your form.

<xpp>

void dynamicButtonControl_Clicked()
{
    ;

    info ("Dynamic button clicked!");
}
boolean dynamicStringControl_Modified()
{
    FormStringControl control = element.controlCallingMethod();
    ;

    info (strFmt("Modified dynamic control %1 to %2", int2str(control.id()), control.text()));
    return true;
}

</xpp> Note that the first part of the handler method names (before the underscore) exactly matches the control names used in init().

Adding menu-item buttons

It is usually preferable to keep the amount of code on a form to a minimum. By setting your dynamically-created buttons to call menu-items, you can avoid writing the event handlers completely.

The following example adds a menu-item button to a form, which will open the SalesTable form using the standard Axapta menu-item. Note that we now must use a FormFunctionButtonControl, rather than a FormButtonControl.

The button will correctly show the label from the menu-item.

<xpp>

public void init()
{
    FormFunctionButtonControl   formFunctionButtonControl;
    ;

    formFunctionButtonControl = this.form().addControl(FormControlType::MenuFunctionButton, "SalesTableButton");
    formFunctionButtonControl.menuItemType(MenuItemType::Display);
    formFunctionButtonControl.menuItemName(MenuItemDisplayStr(SalesTable));

    super();
}

</xpp>

The same principle can be used to call your own 'display', 'output' or 'action' menu-item. This is useful if the button should perform some intensive database processing, which would benefit from being encapsulated in a server-side class.

See the create() method on the KMActionMenuButtonAuto class for a further, more complex example.


See this project for two forms demonstrating the above concepts.

Adding grid control

In most cases you'd better use visible property of this control's type. But sometimes you have to add a grid on an existing form and without any opportunity of change. This example will help you. Rather you are making this modification on forms, that are managed from class. In our tutorial case this is runable tutorial_AddRunTimeControls class. This following code adds a grid control of the selected table. You may find similar functionality in the form SysTableBrowser:

<xpp> void addRunTimeControls(FormRun _formRun) {

    FormGridControl        formGrigControl;
    Form                   _form;
    FormBuildDataSource    formBuildDataSource;
    FormBuildDesign        formBuildDesign;
    FormBuildStringControl formBuildStringControl;
    FormBuildGridControl   formBuildGridControl;
    Object                 formBuildControl;
    FormBuildGroupControl  formGroupControl;
    CustTable              custTable;
    DictTable              dictTable;
    TableId                tableID;
    ;
   // Adding a Grid  control, this used in  SysTableBrowser
   tableID    = picktable();
   dictTable   = new DictTable(tableID);
   _form = _formRun.form();
   formBuildDataSource = _form.dataSource(2);
   formBuildDataSource.name(dictTable.name());
   formBuildDataSource.table(dictTable.id());
   formBuildDataSource.autoQuery(true);
   formBuildDesign = _form.design();
   formBuildDesign.widthMode(-1);
   formBuildDesign.widthValue(600);
   formBuildDesign.heightMode(-1);
   formBuildDesign.heightValue(400);
   formGroupControl = formBuildDesign.addControl(FormControlType::Group, 'SecondGrid');
   formGroupControl.caption("Dynamic Grid");
   formGroupControl.widthMode(1);
   formGroupControl.heightMode(1);
   formBuildGridControl = formGroupControl.addControl(FormControlType::GRID,'Grid');
   formBuildGridControl.dataSource(dictTable.name());
   formBuildGridControl.name('AddRunTime');
   formBuildGridControl.widthMode(1);
   formBuildGridControl.heightMode(1);
   this.showFields(tableNum(custTable), formBuildGridControl, formBuildDataSource);
   _formRun.controlMethodOverload(true);
   _formRun.init();
   _formRun.run();
   _formRun.detach();

} </xpp>

And define the fields on grid.

<xpp> public void showFields(tableId tableId,

                      FormBuildGridControl    formBuildGridControl,
                      FormBuildDataSource     formBuildDataSource)


{

   FormBuildStringControl          formBuildStringControl;
   DictTable                       dictTable;
   fieldId                         fieldId;
   int                             i;
   int                             fieldCnt;
   ;
   dictTable   = new DictTable(tableId);
   for (i=1; i<=3; i++)
   {
       fieldId = dictTable.fieldCnt2Id(i);
       formBuildGridControl.addDataField(formBuildDataSource.id(), fieldId2Ext(fieldId, 1));
   }

} </xpp>