Monday 17 March 2008

Lookup Form

Axapta usually creates required lookup forms on the fly, but it also allows the developer to create a custom lookup form and assign it as "FormHelp" to an extended datatype, so that it is automatically used. Why would you do that? There might be many reasons. Typically you need to display the data in a non standard order or you want to show only a subset of the data depending on some criteria. Here are the steps needed to create a proper lookup form.


Contents


* 1 Assumptions
* 2 Create the form
* 3 Make it selectable
* 4 Make sure the form opens with the previously selected value
* 5 Make lookup react to search by wild card
* 6 Make Form Default lookup for an Extended Data Type

Assumptions

In the following example I assume you create a lookup for table "xyz" and the ID field of that table is called "id".

Create the form

First create a basic form. Usually this form contains not much more than a grid. But you might add additional controls. Then set the following properties on the datasource, so that the form can not be used for editing:

AllowCheck: No
AllowCreate: No
AllowDelete: No
AllowEdit: No
AutoNotify: No
InsertAtEnd: No
InsertIfEmpty: No

Additionally set for the design the following properties to make it look like a proper lookup:

AlwaysOnTop: Yes
Frame: Border
HideToolbar: Yes
WindowType: Popup


[edit] Make it selectable

Now we need to tell the lookup form, which control will return the selected value. Lets assume you have a form with a grid and in that grid you have a control called "xyz_id". In this case you overwrite the init method of the form as shown below. Note that if you are using Axapta v3.0 or higher, then you can set the control's AutoDeclaration property to Yes and use the control name directly in the selectMode() call.

public void init()
{
FormControl xyz_id;
;

super();

xyz_id= element.design().control(control::xyz_id);
element.selectMode(xyz_id);
}

[edit] Make sure the form opens with the previously selected value

Strange enough the following is missing in most/all custom lookup forms, which you find in Axapta Standard. But it is required, if you want your lookup to mark the previously selected value as active record. Therefore overwrite the ExecuteQuery method of your datasource:

public void executeQuery()
{
FormStringControl callerControl = SysTableLookup::getCallerStringControl(element.args());
;

super();

xyz_ds.findValue(fieldnum(xyz,id),callerControl.text());
}

With a lot of pain I had top learn that the above will not work, if you use the standard query, which is automatically created by Axapta. This might be due to existing Dynalinks or other reasons, which I am not aware of. But it will work fine, if you create your own query for example in the Init method of the datasource. Here you can also define your custom sort or range criteria:

public void init()
{
Query q = new Query();
QueryBuildDataSource qbds;
;

super();

qbds = q.addDataSource(tablenum(xyz));
qbds.orderMode(OrderMode::OrderBy);
qbds.addSortField(fieldNum(xyz,some_other_field));
this.query(q);
}

[edit] Make lookup react to search by wild card

The following you will find in the official documentation and also in a lot of Axapta examples. If you type in a standard Axapta StringEdit Control something like "abc*", then automatically the lookup will open and only the matching subset of records will be shown. You achieve this by overwriting the run method of the form:

public void run()
{
FormStringControl callerControl = SysTableLookup::getCallerStringControl(element.args());
Boolean filterLookup = false;
;

// if lookup was called with filter, then supress autoSearch
if (callerControl.text() && callerControl.hasChanged())
{
filterLookup = true;
xyz_ds.autoSearch(false);
}

super();

// after call of super filter search manually by applying past filter
if (filterLookup)
{
xyz_ds.research();
xyz_ds.filter(fieldnum(xyz,id),callerControl.text());
}
}

Make Form Default lookup for an Extended Data Type

To have Axapta use your form by default every time a lookup is performed, you can set your form's name in the Extended Data Type's property called 'FormHelp'. You do not necessarily need a display menu item, the property is your actual form's name.

So that's it. Now you have a wonderfully working custom lookup.

6 comments:

Anonymous said...

If you are looking up a customer thru the Account Number Field can the lookup searh the Customer Name by default and return the customer number. I do not know the customer number but I do know the customer name, therefore I would like to search by customer name. The same goes for the Vendors.

Arifin said...

Hello, I'm still not clear with the last step of creating form lookup. What should I do to connect the field in a form to my form lookup?

Truong Cong Da said...

"What should I do to connect the field in a form to my form lookup?
"

You should assign FormHelp properties of your ETD to your look-up form. :)

Anonymous said...

HI! thank you for the usefull post.
what can i do to improve performance when the datasource contains a large quantity of records? I mean: if i type "A*" the form opens immediatly, but if I type "q*" it runs slowly(it takes few seconds)...

Arifin said...

Hello, thank you for the latest help :)

Unfortunately I didn't use that method at that time, but now I really need to do this. I have a problem with 'control::xyz_id', why I can't find my control at that enum ?

Anonymous said...

Hi
Is there anyway I can get the wildcard to work without typing in "*" but instead just react to my typing?