Default data wizards in Dynamics AX extend standard
wizard functionality. Basically, both types of wizards do more or less
the same task, but default data wizards are more oriented towards
setting up initial data, which is not company specific. One of the
examples in the standard application is the Unit creation wizard in Basic | Setup | Units.
This wizard populates the table of units of measure with default data
depending on the user selections during the running of the wizard.
Also it is good
practice to provide default data wizards along with custom Dynamics AX
modules. It can make the setup easier, saves the user's time, and makes a
good impression about how user-friendly the software is.
In this recipe, we will
create a new default data wizard. We will use the wizard for creating
several new document types for document handling. If there are no
document types initially, the standard application creates a number of
basic types. Our wizard will be a supplement to this and will create two
new document types for storing purchase documents.
How to do it...
1. Run the Wizard Wizard from Tools | Development tools | Wizards. Click Next on the first page:
2. Select Default data Wizard on the second page and click Next:
3. Type DocuType in the Specify the name of your wizard input box and click Next:
4. Click Next on the following page accepting the default value:
5. Also accept the default on this page and click Next:
6. Click Finish on the last page:
7. Once completed, Wizard Wizard creates a new development project containing a new class, form, and menu item:
8. In AOT, find the existing DocuTypeDefaultData class, remove the abstract modifier from its class declaration, and add a DocuType variable:
class DocuTypeDefaultData extends SysDefaultData
{
DocuType buffer;
}
9. Override following the methods in this class:
public Common buffer()
{
return buffer;
}
protected fieldId keyFieldId()
{
return fieldnum(DocuType, TypeId);
}
protected void setBuffer()
{;
if (form_ds)
{
buffer = form_ds.cursor();
}
}
protected void doTable(boolean useCurBuffer)
{
void insert()
{
if (!this.existDB())
{
buffer.insert();
}
}
;
buffer.initValue();
buffer.TypeId = "PO";
buffer.Name = "Purchase order";
buffer.ActionClassId = classnum(DocuActionArchive);
insert();
buffer.initValue();
buffer.TypeId = "PI";
buffer.Name = "Purchase invoice";
buffer.ActionClassId = classnum(DocuActionArchive);
insert();
}
protected boolean existTmp(DocuType _bufferToCheck)
{
DocuType bufferExist;
;
default data wizarddefault data wizardcreating, stepsbufferExist = this.makeTmp();
select firstOnly bufferExist
index hint TypeIdx
where bufferExist.TypeId == _bufferToCheck.TypeId
&& bufferExist.RecId != _bufferToCheck.RecId;
return bufferExist.RecId ? true : false;
}
public int64 createdNumDB()
{
return (select count(RecId) from DocuType).RecId;
}
10. Create a class constructor:
public static DocuTypeDefaultData construct()
{
return new DocuTypeDefaultData();
}
11. Find SysDefaultData in AOT and modify its constructVAR():
static SysDefaultData constructVAR(tableId tableId)
{;
switch (tableId)
{
case tablenum(DocuType):
return DocuTypeDefaultData::construct();
}
return null;
default data wizarddefault data wizardcreating, steps}
12. Add the following variable to the class declaration of the DocuTypeDefaultDataWizard class:
DocuTypeDefaultData docuTypeDefaultData;
13. Override its init():
boolean init()
{
boolean ret;
;
docuTypeDefaultData =
SysDefaultData::newDefaultDataWizard(
tablenum(DocuType),
this);
ret = super();
return ret;
}
14. Create a new method:
DocuTypeDefaultData docuTypeDefaultData()
{
return docuTypeDefaultData;
}
16. Add a new data source to the DocuTypeDefaultDataWizard form:
Property
|
Value
|
---|
Name
|
DocuType
|
Table
|
DocuType
|
AllowEdit
|
No
|
AllowCreate
|
No
|
AllowDelete
|
No
|
17. Override the table's method:
public void init()
{;
super();
DocuType.setTmp();
DocuType.checkRecord(false);
}
18. Change the properties of the Step1 tab page:
Property
|
Value
|
---|
Caption
|
Welcome
|
19. Add a StaticText control to this tab page and set its properties:
Property
|
Value
|
---|
Name
|
WelcomeTxt
|
Text
|
This default data wizard creates two new document types.
|
Width
|
Column width
|
Height
|
Column height
|
20. Change the properties of the Step2 tab page:
Property
|
Value
|
---|
Caption
|
Document types
|
HelpText
|
Create document types
|
AutoDeclaration
|
Yes
|
21. Add a Grid control to this tab page and change its properties:
Property
|
Value
|
---|
Name
|
Grid
|
DataSource
|
DocuType
|
22. Add a new StringEdit control to the grid with the following properties:
Property
|
Value
|
---|
Name
|
TypeId
|
DataSource
|
DocuType
|
DataField
|
TypeId
|
23. Add another StringEdit control to the grid with the following properties:
Property
|
Value
|
---|
Name
|
Name
|
DataSource
|
DocuType
|
DataField
|
Name
|
24. Add one more StringEdit control to the grid with the following properties:
Property
|
Value
|
---|
Name
|
ActionClassName
|
DataSource
|
DocuType
|
DataMethod
|
ActionClassName
|
25. Change the properties of the Step3 tab page:
Property
|
Value
|
---|
Caption
|
Finish
|
AutoDeclaration
|
Yes
|
26. Add a new StringEdit control to this tab page:
Property
|
Value
|
---|
Name
|
FinishTxt
|
AutoDeclaration
|
Yes
|
AllowEdit
|
No
|
Width
|
Column width
|
Border
|
None
|
27. Add a new ListView control to the same tab page:
Property
|
Value
|
---|
Name
|
FinishListView
|
Width
|
Column width
|
Height
|
Column height
|
ViewType
|
Report
|
28. Add the following code to the form's init():
sysWizard.docuTypeDefaultData().parmForm_DS(DocuType_ds);
sysWizard.docuTypeDefaultData().init();
sysWizard.summaryInit(FinishListView);
right after this line:
sysWizard = element.Args().caller();
29. Create a new form method:
void initPage()
default data wizarddefault data wizardcreating, steps{;
switch (true)
{
case Step2.isActivePage():
sysWizard.docuTypeDefaultData().createTable();
break;
case Step3.isActivePage():
sysWizard.summaryBuild(
finishListView,
FinishTxt);
break;
}
}
30. To test the results, run the DocuTypeDefaultDataWizard menu item. The wizard should appear. Click Next on the first page:
31. Review the document types to be created and click Next:
32. On the last page click Finish to create two new document types:
33. To check the results, open Basic | Setup | Document management | Document types and find the two types newly created by the wizard:
How it works...
To create a framework for a new default data wizard we use the Wizard Wizard from the Development tools menu. On the second page, we have to select the Default data Wizard
option, type in the wizard name on the third page, and accept the
defaults on the rest of the pages. Of course, we could have created new
wizard from scratch, but the Wizard Wizard
saves a lot of time. The created menu item starts the wizard, the
created class includes all the wizard logic, and created form presents
the user with an interface. In this form each tab page corresponds to
one wizard step.
Next, we need to create a new class derived from SysDefaultData
for every type of default data we are going to use. In this example, we
are populating a single table so it will be sufficient to create one
class. The purpose of this class is to handle the data and table being
updated. By following Dynamics AX naming conventions, the class name
should be suffixed with the DefaultData string, that is, DocuTypeDefaultData.
Such a class already exists in the application but it is empty and is
not used— most likely it is reserved for future use. So no
harm will be done if we use it for this demonstration, we just have to
remove the abstract modifier from its class declaration.
The class should implement a number of methods, which are declared as abstract in the parent SysDefaultData
class. Each abstract method in the latter class contains a brief
developer comment on how to use each method. Here are the overridden
methods:
buffer(): returns the current record.
keyFieldId(): returns the key field number of the table being updated.
setBuffer(): sets the buffer variable.
doTable(): inserts the data into a temporary table during the wizard run and into the actual table, once the wizard is completed.
existTmp(): checks whether a record exists in the temporary table.
createdNumDB(); returns how many records exist in a table being updated.
The created class should have its own construct() method and also has to be included into the constructVAR() method of SysDefaultData (construct() in SysDefaultData is used for system classes).
The following step is to modify the created DocuTypeDefaultDataWizard class. First, we add a variable of type DocuTypeDefaultData into its class declaration. Then, we initialize the variable in the class init() and create a method that returns that variable. Finally, we have to delete the run() created by the Wizard Wizard, because we do not have any specific logic to be implemented here and we can use the parent's run().
The final step is to modify the form. We start with adding the DocuType
table to the form and declaring this data source as temporary. On the
first tab page (first wizard page) we add welcome text and description.
On the second one, along with descriptive texts, we add a grid control
with three fields from the DocuType table. This is where the user can review the data. Normally, here the user would be allowed to change the data. In such case, validateWrite()
on the data source has to be overridden with a call to the wizard class
to validate the data. The third page contains finishing text and a ListView control to show the existing number of records against how many will be created.
In the form's init(), we place the code that initializes the wizard handling class and in the initPage(),
some logic to be executed on some wizard steps. On the second page, we
initialize temporary data to be loaded and on the third page, we
populate the ListView control with the summarized data.