0

The combination of the x++ multiselect lookup pattern and the syslookupmultiselectctrl in x++ class gives you a powerful, reusable way to let users pick multiple records. For a beginner, the key is to understand the flow—construct the control, get/set values, and store them. For an intermediate developer, the next step is integrating with contracts, JSON, and reports so these selections can drive business processes across modules like retail, warehousing, and manufacturing.

When building solutions in Dynamics 365 Finance & Operations (D365FO), developers often need to let users select multiple records at once—for example, picking a set of warehouses, customers, or products. Two key concepts that make this possible are the x++ multiselect lookup pattern and the SysLookupMultiSelectCtrl framework class.

This guide introduces both concepts with simple explanations, code snippets, and a practical warehousing scenario that makes it easier to connect the dots.


What is a Multi-Select Lookup?

A normal lookup lets a user pick one value—say, a single customer account or one warehouse. But business processes often need several values at the same time. For example:

  • Retail planners may want to release orders to multiple warehouses.
  • Manufacturing staff may assign work to several sites.
  • Buyers may filter reports by multiple vendors.

A multi-select lookup extends the usual dropdown into a grid-style dialog where multiple rows can be chosen. The system stores those choices as a container of RecId values, which can then be saved in a table or passed into a process.


Using SysLookupMultiSelectCtrl in X++

The standard controller for multi-select lookups is SysLookupMultiSelectCtrl. It attaches to a form or dialog control, manages the lookup dialog, and gives you methods to read or set the chosen records. The pattern looks like this:

  1. Declare the controller in your form or dialog class.
  2. Construct it in init() with a query and the fields you want to show.
  3. Use get() and set() to read or pre-load selections.

Example: Multi-Select Warehouses

Imagine a retailer managing electronic goods who needs to pick multiple warehouses for order fulfillment. Here’s a compact example inside a form:

// Class declaration
SysLookupMultiSelectCtrl msCtrlWarehouse;

// Init method
public void init()
{
    super();

    msCtrlWarehouse = SysLookupMultiSelectCtrl::construct(
        element,
        StringEdit_WarehousePick,                // form control (AutoDeclaration = Yes)
        querystr(InventLocation),                // base query on InventLocation
        false,                                   // same legal entity
        [tableNum(InventLocation), fieldNum(InventLocation, InventLocationId),
         tableNum(InventLocation), fieldNum(InventLocation, Name)] // display cols
    );

    // Pre-load from saved parameters
    if (RetailWHSParameters.WarehouseSelCon)
    {
        msCtrlWarehouse.set(RetailWHSParameters.WarehouseSelCon);
    }
}

// Modified method
public boolean modified()
{
    boolean ret = super();
    RetailWHSParameters.WarehouseSelCon = msCtrlWarehouse.get(); // save RecIds
    RetailWHSParameters.update();
    return ret;
}

Here, the user can tick several warehouses, and the system saves their RecIds into a container field on a parameter table.


Multi-Select in Reports or Dialogs

When you use the SysOperation framework (for reports or batch jobs), you can combine SysLookupMultiSelectCtrl with a [DataContract] class:

[DataContract]
class RetailWaveContract
{
    List warehouseRecIds; // store selected warehouses

    [DataMember("WarehouseRecIds")]
    [DataCollection(Types::Int64)]
    public List parmWarehouseRecIds(List _v = warehouseRecIds)
    {
        warehouseRecIds = _v;
        return warehouseRecIds;
    }
}

A UIBuilder class attaches the multi-select controller to the dialog field, reads values into the contract, and later your service or controller uses the List of RecIds to apply ranges or business logic.


JSON Integration with Data Contracts

Sometimes you need to persist selections or send them to an external system. With [DataContract] and [DataMember] attributes in place, you can easily convert your contract to JSON:

// Serialize
str json = FormJsonSerializer::serializeClass(contractInstance);

// Deserialize
RetailWaveContract contract2 =
    FormJsonSerializer::deserializeObject(classNum(RetailWaveContract), json);

This allows multi-select results to travel safely across integrations, APIs, or saved parameter profiles.

Have a Question ?

Fill out this short form, one of our Experts will contact you soon.

Talk to an Expert Today

Call Now

Call Now800-453-5961