How to create multi-select lookup dialog for class in AX 2012

Create these methods in your class:

class DICPromotion2SalesLine extends Runbase
{
    
    DialogRunbase               dialog;
    DialogGroup                 dialogGrp;
    
    FormBuildStringControl      fbsCtrlPromotion;
    FormStringControl           fsCtrlPromotion;
    container                   returnPromotion;
    SysLookupMultiSelectCtrl    msCtrlPromotion;
    str                         promotionRange;
}

protected Object dialog()
{
    FormBuildControl    setupGroupControl;
    ;
    dialog = super();
    dialog.alwaysOnTop(true);
    dialog.windowType(FormWindowType::Standard);
    dialogGrp = dialog.addGroup('Promotion');
    setupGroupControl = dialog.formBuildDesign().control(dialogGrp.formBuildGroup().id());
    fbsCtrlPromotion = setupGroupControl.addControl(FormControlType::String, identifierstr(DICPromotionID));
    fbsCtrlPromotion.label('Promotion id');
    dialog.allowUpdateOnSelectCtrl(true);
    this.dialogSelectCtrl();

    return dialog;
}
public void dialogPostRun(DialogRunbase _dialog)
{
    FormRun formRun;

    super(dialog);

    formRun = _dialog.dialogForm().formRun();

    if (formRun)
    {
        fsCtrlPromotion = formRun.design().control(fbsCtrlPromotion.id());
/// you can build with your own query, or created query in system by method construct
        msCtrlPromotion = SysLookupMultiSelectCtrl::constructWithQuery(formRun, fsCtrlPromotion, this.buildQuery());
    }
}

// build your Query here
public query buildQuery()
{
    Query                   q          = new Query();
    QueryBuildDataSource    qbds;
    DICTmpPromotionTable    tmpPromotionTable;
    ;  
    qbds    = q.addDataSource(tablenum(DICPromotionMaster));
    qbds.addSelectionField(fieldNum(DICPromotionMaster, PromotionID));
    qbds.addSelectionField(fieldNum(DICPromotionMaster, Description));
    qbds.addSelectionField(fieldNum(DICPromotionMaster, WithGroupItem));
    qbds.addSelectionField(fieldNum(DICPromotionMaster, Fromdate));
    qbds.addSelectionField(fieldNum(DICPromotionMaster, ToDate));   
        
    tmpPromotionTable = this.searchPromotion();
    while select tmpPromotionTable
    {
        qbds.addRange(fieldNum(DICPromotionMaster,PromotionID)).value(tmpPromotionTable.PromotionID);        
    }
    return q;
}

public boolean getFromDialog()
{
    boolean         ret;
    #Characters
    
    ret = super();
   
    if (msCtrlPromotion)
    {
        returnPromotion = msCtrlPromotion.getSelectedFieldValues(); // get actual value of the selected rows
        returnPeriodRecId = msCtrlPromotion.get();  // get RecIds of the selected rows  (it's very useful when you want to look one field and return another field value)  
    }
    promotionRange    = con2StrUnlimited(returnPromotion,#comma);
   
    return ret;
}