Get selected records in Dynamics AX 2012

In my earlier post, we discussed how we can retrieve all selected records on a list page. You can read that post here.

Retrieving all selected records from a caller form is very easy. The code for this can be found in a number of places in standard Dynamics AX codebase. The general approach is to use the dataSource.getFirst(1) statement to get the first selected record and loop through the remaining using dataSource.getNext().

In Dynamics AX 2009, a new class was introduced for this purpose. This was the MultiSelectionHelper class.

In Dynamics AX 2012, another new class has been introduced to retrieve the selected records. This is the MultiSelectionContext class.

The MultiSelectionHelper class is an application class. It presents two constrcutors. The standard constructor method just creates a new instance of the MultiSelectionHelper class. When this construct is used, you will have to explicitly set the dataSource to be used for fethcing selected records. This can be done in the following way,
MultiSelectionHelper multiSelectionHelper; 

multiSelectionHelper = MultiSelectionHelper::construct();
multiSelectionHelper.parmDatasource(element.dataSource());
This way, the class is initialized and the datasource is specified.

The other constructor method this class offers is the createFromCaller() method. This method takes a formRun as an argument. When you want to retrieve the selected records from the caller form, you can pass the caller form as an argument here.

Once the class has been initialized, you can traverse through the selected records using the getFirst() & getNext() method.

The MultiSelectionHelper class provides the added benefit of caching the selected records if the object is initialized on the server.

The other new class that has been introduced in Dynamics AX 2012 for selected records handling is MultiSelectionContext. This is a kernel class. An object of this class exists in the xArgs class. This class also provides the getFirst() and getNext() methods to traverse through the selected records.

Below is a code sample on how these two classes can be used to implemented in code.
public void init()
{
    FormRun                 callerForm;
    FormDataSource          formDataSource;

    MultiSelectionHelper    multiSelectionHelper;
    MultiSelectionContext   multiSelectionContext;

    ProjTable       projTable;

    super();

    if (!element.args().caller())
    {
        throw error("@SYS22539");
    }

// ************** The standard way of doing it in Dynamics AX 4 and Dynamics AX 2009 **************
    callerForm = element.args().caller();
    formDataSource = callerForm.dataSource();

    ListView.add("Approach 1");

    for(projTable = formDataSource.getFirst(1); projTable; projTable = formDataSource.getNext())
    {        
        ListView.add(strFmt("%1 - %2",projTable.ProjId, projTable.Name));
    }

// ************** Using the new MultiSelectionHelper class in Dynamics AX 2012 **************
    multiSelectionHelper = MultiSelectionHelper::createFromCaller(element.args().caller());

    projTable = multiSelectionHelper.getFirst();
    ListView.add("Approach 2");

    while (projTable)
    {        
        ListView.add(strFmt("%1 - %2",projTable.ProjId, projTable.Name));
        projTable = multiSelectionHelper.getNext();
    }

// ************** Using the new MultiSelectionContext class in Dynamics AX 2012 **************
    multiSelectionContext = element.args().multiSelectionContext();

    projTable = multiSelectionContext.getFirst();
    ListView.add("Approach 3");

    while (projTable)
    {        
        ListView.add(strFmt("%1 - %2",projTable.ProjId, projTable.Name));
        projTable = multiSelectionContext.getNext();
    }

    if (!ListView.getCount())
    {
        throw error("No projects selected");
    }
}
The below image shows which part of the code produced the what output.
Going forward, I'll recommend that we start using these helper classes for dealing with selected records.

Some of you may have a question as to which class to use and in what scenarios. Let me clarify that for you.

Like I stated above, the MultiSelectionHelper class provides us the benefit of record caching provided you intantiate the object on the server tier. Now, because of this, you will have to call this class from within an object(not a form as forms run on the client tier) which is running on the server tier. This is because the RunOn property of the MultiSelectionHelper class is CalledFrom. So if you call it directly from a form, the object will be created on the client tier itself and your selected records will not be cached.

But if you have designed your code such a way that your form calls a table or a class running on the server tier, and then this class in turns calls the MultiSelectionHelper class, we can then make use of the caching capabilities.

So if your code is designed in such a way, I'll advice to make use of the MultiSelectionHelper class else you should go for the MultiSelectionContext class.

You can download the project I've developed for this demo here. Click on the Project details button on the Projects list page to open the new form.

I hope this post was helpful. Please feel free to provide your comments.

Thats all for today, do check back soon for more.

Comments

Since you are basically trying to implement the Iterator(Enumerator) pattern, i would suggest that you have a method called MultiSelectionHelper.HasMore() or something, that would return true if the record read is still OK
Zubair Ahmed said…
Hi Vanya,

This is a standard class and as such doesnt have an implementation for HasMore.
Anonymous said…
Hello

Its important to point out that the MultiSelectionContext class only works if the marked record is "selected" using the checkbox on the left side in a grid (2012 new feature). If the record is only marked but not "selected" then the MultiSelectionContext class will not find the record. The MultiSelectionHelper helper class on the other hand, finds the "marked" record even if it is not "selected".

-Peter
wojzeh said…
Hi Zubair!

Thank you for this posting!

I just wonder how we can deal with a form with a few tables like that On-hand?

There are three different tables placed on that; so how can I get the values from them?
Zubair Ahmed said…
Hi Wojzeh,

You can basically loop through all form datasources from the formRun object and use cursor() method to get the current record.

Popular posts from this blog

How to add empty ranges in query

The field with ID '0' does not exist in table - Cause and resolution.