Hide objects on a Form based on user roles

In this section I will be demonstrating how to hide action panes, action pane tabs, buttons, command buttons etc via adding chain of command to FormRun class.

Uğur Yıldız - Junior Software Developer

Creating few parameter tables will be helpful.

DAXMetadataHelper
using Microsoft.Dynamics.Ax.Xpp.MetadataSupport;
using Microsoft.Dynamics.AX.Metadata.MetaModel;
using System.Reflection;

 public class DAXMetadataHelper
 {
 
     container controlNames;
 
     public static void fillFormNamesTable()
    {
        DAXFormNameListTable FormList;
        var formsList = Xpp.MetadataSupport::FormNames();
        
        ttsbegin;
        delete_from FormList;
        
        while(formsList.MoveNext())
        {
            AxForm form = Xpp.MetadataSupport::GetForm(formsList.Current);
            
            FormList.clear();
            FormList.Name = form.Name;
            FormList.Label = SysLabel::labelId2String2(form.Design.Caption);
            FormList.insert();
            
        }
        ttscommit;
    }
    
    public static void fillControlNames(container _controlNames)
    {
        DAXTmpFormItemNamesLookup DAXTmpFormItemNamesLookup;
        ttsbegin;
        delete_from DAXTmpFormItemNamesLookup;

        for(int i=1;i<=conLen(_controlNames);i++)
        {
            DAXTmpFormItemNamesLookup.clear();
            DAXTmpFormItemNamesLookup.ControlName = strFmt("%1",conPeek(_controlNames,i));
            DAXTmpFormItemNamesLookup.insert();
        }
        ttscommit;
    }
    
    public container getControlNames(str _formName,DAXFormItemTypes _itemType)
    {
        AxForm Axform =  Microsoft.Dynamics.Ax.Xpp.MetadataSupport::GetForm(_formName);
        AxFormExtension AxFormExtension;
        this.showControlNames(Axform.Design,_itemType);
        

        System.Collections.IList list =  Microsoft.Dynamics.Ax.Xpp.MetadataSupport::GetFormExtensionNamesNonGeneric(_formName);
        System.Collections.IEnumerable enumerable;
        enumerable = list as System.Collections.IEnumerable;
        System.Collections.IEnumerator enumerator = enumerable.GetEnumerator();

        while(enumerator.MoveNext())
        {
            IFormControlCollection extensionControls;
            AxFormExtension = Microsoft.Dynamics.Ax.Xpp.MetadataSupport::GetFormExtension(enumerator.Current);
            var enumeratorExtension = AxFormExtension.Controls.GetEnumerator();
            while (enumeratorExtension.MoveNext())
            {
                AxFormExtensionControl extControl = enumeratorExtension.Current;
                this.checkControlTypeExtension(_itemType,extControl);
            }
            
        }

        return controlNames;
    }

    public void showControlNames(IFormControlCollection _control,DAXFormItemTypes _itemType)
    {
        var controlEnumerator = _control.Controls.GetEnumerator();
        
        while (controlEnumerator.MoveNext())
        {
            AxFormControl control = controlEnumerator.Current;
            if (control is IFormControlCollection)
            {
                this.checkControlType(_itemType,control);
                this.showControlNames(control as IFormControlCollection,_itemType); // Recursion
            }
            else
            {
                this.checkControlType(_itemType,control);
            }
        }
    }

    public void checkControlType(DAXFormItemTypes_itemType,AxFormControl _control)
    {
        switch (_itemType)
        {
            case DAXFormItemTypes::ActionPane :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ActionPane)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::ActionPaneTab :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ActionPaneTab)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::Button :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::Button)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::ButtonGroup :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ButtonGroup)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::CommandButton :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::CommandButton)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::DropDialogButton :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::DropDialogButton)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::MenuButton :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::MenuButton)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::MenuFunctionButton :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::MenuFunctionButton)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::FormTab :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::Tab)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;

            case DAXFormItemTypes::FormTabPage :
                if(_control.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::TabPage)
                {
                    controlNames += strFmt("%1",_control.Name);
                }
                break;
        }
    }

    public void checkControlTypeExtension(DAXFormItemTypes _itemType,AxFormExtensionControl _control)
    {
        switch (_itemType)
        {
            case DAXFormItemTypes::ActionPane :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ActionPane)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::ActionPaneTab :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ActionPaneTab)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::Button :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::Button)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::ButtonGroup :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::ButtonGroup)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::CommandButton :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::CommandButton)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::DropDialogButton :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::DropDialogButton)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::MenuButton :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::MenuButton)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::MenuFunctionButton :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::MenuFunctionButton)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::FormTab :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::Tab)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;

            case DAXFormItemTypes::FormTabPage :
                if(_control.FormControl.type == Microsoft.Dynamics.AX.Metadata.Core.MetaModel.FormControlType::TabPage)
                {
                    controlNames += strFmt("%1",_control.FormControl.Name);
                }
                break;


        }
    }
 }                       

Assume you have a table named FormNameListTable which has Name and Label fields to fill. This table will be used to let user choose a form name from lookup. To prevent having duplicate records you could use index on your table but whenever a new form is added to the system you should populate records again to get new ones so it's better to delete every record from the table and fill it again. With this function you'll be having all the form names on the AOT browser.

Next create a new table DAXFormHideParameters. See expandable content for fields. After creating a new form we add this table as datasource and overriding "Lookup" method of FormName field. By overriding lookup we let user to choose a form from lookup.

Table : DAXFormHideParameters
  • FormName

  • ControlType -> Enum Type : DAXFormItemTypes

  • ControlName

  • RunType -> Enum Type : DAXFormFilterRunMode

  • UserRole -> EDT : SecurityRoleName

FormName Field Lookup Method
    [DataField]
    class FormName 
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name = "_formControl"></param>
        /// <param name = "_filterStr"></param>
        public void lookup(FormControl _formControl, str _filterStr)
        {
            //super(_formControl, _filterStr);
            Query query = new Query();
            QueryBuildDataSource queryBuildDataSource;
           
            DAXMetadaHelper::fillFormNamesTable();
            
            SysTableLookup sysTableLookup;
            sysTableLookup = SysTableLookup::newParameters(tableNum(DAXFormNameListTable),_formControl);
            sysTableLookup.addLookupField(fieldNum(DAXFormNameListTable,Name));
            sysTableLookup.addLookupField(fieldNum(DAXFormNameListTable,Label));
            queryBuildDataSource = query.addDataSource(tableNum(DAXFormNameListTable));
            sysTableLookup.parmQuery(query);
            sysTableLookup.performFormLookup();
        }
    
    }

Create a new Enum (DAXFormItemTpes) to let user decide what kind of control we are going to work on. Use this enum for ControlType field.

Enum Values for DAXFormItemTypes
  • Null

  • ActionPane

  • ActionPaneTab

  • ButtonGroup

  • Button

  • CommandButton

  • MenuFunctionButton

  • MenuButton

  • DropDialogButton

  • FormTab

  • FormTabPage

Enum Values for DAXFormFilterRunMode
  • Hide

  • Disable

Next up we are going to override lookup method of ControlName field. Create a new table to use as lookup for form controls. Just one field should be enough.

DAXTmpFormItemNamesLookup (Field : ControlName)

ControlName Field Lookup Method
[DataField]
    class ControlName 
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name = "_formControl"></param>
        /// <param name = "_filterStr"></param>
        public void lookup(FormControl _formControl, str _filterStr)
        {
            //super(_formControl, _filterStr);

            if(DAXFormHideParameters.ControlType == DAXFormItemTypes::Null)
            {
                throw error("Please select a control type first.");
            }
            Query query = new Query();
            QueryBuildDataSource queryBuildDataSource;
            
            DAXMetaDataHelper DAXMetaDataHelper = new DAXMetaDataHelper();
            container controls = DAXMetaDataHelper.getControlNames(DAXFormHideParameters.FormName,DAXFormHideParameters.ControlType);

            DAXMetaDataHelper::fillControlNames(controls);

            SysTableLookup sysTableLookup;
            sysTableLookup = SysTableLookup::newParameters(tableNum(DAXTmpFormItemNamesLookup),_formControl);
            sysTableLookup.addLookupField(fieldNum(DAXTmpFormItemNamesLookup,controlName));
            queryBuildDataSource = query.addDataSource(tableNum(DAXTmpFormItemNamesLookup));
            sysTableLookup.parmQuery(query);
            sysTableLookup.performFormLookup();
        }

    }

Thanks to Martin Dráb for providing method to get control names from a form.

Once finishing creating tables, helper methods etc it's time to write extension for FormRun.

FormRun_DAX_Extension
[ExtensionOf(classStr(FormRun))]
final class FormRun_Dax_Extension
{
    public void init()
    {
        next init();

        this.hideButtonAndFields();
        
    }
    
    public void hideButtonAndFields()
    {
        if(!Global::DAXisSysAdmin())
        {
            if(DAXFormHideParameters::checkExists(this.form().name()))
            {
                DAXFormHideParameters   DAXFormHideParameters;
                UserId curUserId = curUserId();

                Query query = new Query();
                QueryBuildDataSource qbds1,qbds2,qbds3;
                QueryBuildRange qbr;
                QueryRun qr;

                qbds1 = query.addDataSource(tableNum(DAXFormHideParameters));

                qbds2 = qbds1.addDataSource(tableNum(SecurityRole));
                qbds2.joinMode(JoinMode::InnerJoin);
                qbds2.addLink(fieldNum(DAXFormHideParameters,UserRole),fieldNum(SecurityRole,Name));

                qbds3 = qbds2.addDataSource(tableNum(SecurityUserRole));
                qbds3.joinMode(JoinMode::InnerJoin);
                qbds3.addLink(fieldNum(SecurityRole,RecId),fieldNum(SecurityUserRole,SecurityRole));

                qbr = qbds1.addRange(fieldNum(DAXFormHideParameters,FormName));
                qbr.value(queryValue(formNameLCL));

                qbr = qbds1.addRange(fieldNum(DAXFormHideParameters,ControlName));
                qbr.value(queryValue(SysQuery::valueNotEmptyString()));

                qbr = qbds1.addRange(fieldNum(DAXFormHideParameters,UserRole));
                qbr.value(queryValue(SysQuery::valueNotEmptyString()));

                qbr = qbds3.addRange(fieldNum(SecurityUserRole,User));
                qbr.value(queryValue(curUserId));

                qr = new QueryRun(query);

                while(qr.next())
                {
                    DAXFormHideParameters = qr.get(tableNum(DAXFormHideParameters));

                    if(DAXFormHideParameters)
                    {
                        FormControl FC = this.design().control(this.controlId(DAXFormHideParameters.ControlName));
                        if(FC)
                        {
                            if(DAXFormHideParameters.RunType == DAXFormFilterRunMode::Hide)
                                FC.visible(false);
                            
                            if(DAXFormHideParameters.RunType == DAXFormFilterRunMode::Disable)
                                FC.enabled(false);
                        }
                    }
                }
            }
        }
    }
}

Last updated