Sunday, January 6, 2013

Multi-select on form datasource grid : MultiSelectionHelper

In Dynamics AX it has traditionally been somewhat cumbersome to iterate the selected records on a form datasource. The main issue is that there is a difference in iterating depending on how and what the user has selected!

For example, I have a simple form with a grid. The form has three buttons with their clicked method overwritten.


Dynamics AX allows you to iterate marked records on the grid. Assume our datasource is called "InventItemGroup", which means we can access the object using "InventItemGroup_DS". To iterate the marked records, you can call getFirst, and inside a loop call .getNext() until no more record is returned. The below code is the code behind door, erh, button number 1.

void clicked()
{
    InventItemGroup itemGroup;

    itemGroup = InventItemGroup_DS.getFirst(1);
    while (itemGroup.RecId != 0)
    {
        info(itemGroup.ItemGroupId);

        itemGroup = InventItemGroup_DS.getNext();
    }
}


Looks good. Unfortunately, this works ONLY when you actually MARK a record (in versions prior to AX 2012, when you click the little button in front of a row, in AX2012 when you click the checkbox). If you just select a line by clicking in one of the columns, the one record will not be picked up.

For example, this scenario results in, well, nothing.


These two examples below will result in the expected behavior (getting the item group in the infolog, that is).



As I'm sure you aware, you can also get the current record by just accessing the datasource directly. In the case of our example, InventItemGroup.

void clicked()
{
    info(InventItemGroup.ItemGroupId);
}


With one record selected, this obviously will work. So what happens with multiple records select? It will give you back the LAST record you clicked on. As an example, click one record, then hold the CTRL button on your keyboard pressed and select the next record. The code above will return the ItemGroupId of the last record you clicked on. If you reverse the order in which you clicked the records, you will see that.

So now, the easy way to fix this, is to combine both methods. This is "traditional" code as seen in all versions of Dynamics AX. If the getFirst() method does not return anything, take the datasource cursor instead.

But of course, there's a better way in Dynamics AX 2012. A class called "MultiSelectionHelper" will do the heavy lifting for you. It does in fact do some extra checking as well, feel free to read the code behind it.

void clicked()
{
    InventItemGroup itemGroup;
    MultiSelectionHelper helper = MultiSelectionHelper::construct();
    
    helper.parmDatasource(InventItemGroup_DS);

    itemGroup = helper.getFirst();
    while (itemGroup.RecId != 0)
    {
        info(itemGroup.ItemGroupId);

        itemGroup = helper.getNext();
    }
}



Happy coding. :-)

8 comments:

  1. For the pre-AX2012 readers here, the resolution would be code like this:

    void clicked()
    {
    InventItemGroup itemGroup;

    itemGroup = InventItemGroup_DS.getFirst(1);
    if (itemGroup.RecId != 0)
    {
    do
    {
    info(itemGroup.ItemGroupId);

    itemGroup = InventItemGroup_DS.getNext();
    }
    while (itemGroup.RecId != 0);
    }
    else
    {
    info(InventItemGroup.ItemGroupId);
    }
    }

    ReplyDelete
  2. Hi Joris,
    I believe the multi selection helper was introduced in AX2009.
    I wrote a couple of posts.
    http://dynamicsnavax.blogspot.com.au/search?q=multiselectionhelper

    Code is hard to read if I post it here. I usually use the "for" loop.
    Each one has its place.

    ReplyDelete
    Replies
    1. Ah, cool. I had never noticed it in any standard AX 2009 code, but I ran across it in some AX 2012 code, so I just assumed it was new.
      Should have checked it. Thanks for posting!

      Delete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
  4. Nicely written.
    However I hv a scenario. I wish to loop through all my selected rows plus performs a group by on them using multiselectionhelper.
    Is it possible?

    ReplyDelete
    Replies
    1. modify your code in the row count (in multiselectionhelper class) - its very easy! :)

      Delete
  5. I have followed these guidelines, but my form is still using the last selected row. Any ideas on why is this still happening?

    ReplyDelete