How to remove enum values from dialogs in Dynamics AX?


Hello readers,

A common requirement which I have come across from time to time is the ability to hide certain enum elements on a form. There has been various solutions to the problem. The easiest one I saw was where the developer had created two enums, one with all the values and another one with the unwanted elements dropped. This approach has many problems as comparing the enum values in code isn't possible.
In Dynamics AX 2009, the SysFormEnumComboBox class was provided to solve this issue. You pass it the combo box control's id, the enum to be used and a set of allowed values that need to be shown and it works as a charm. This approach can be used effortlessly on forms.

Recently, I was posed if this can be done on a dialog. Well, its not as simple to use this on a dialog but I have another solution for the problem. Let us see this in more detail here.

I've a very simple dialog with just the SysDimension enum showing up. The requirement is to remove the Purpose element. For that, we need to first get the combo box control, and then remove the element.
We cannot write this code in the dialog() method because the formRun object of the dialog isn't created yet.
We should put this code in dialogPostRun()
public void dialogPostRun(DialogRunbase _dialog)
{
    FormRun             formRun;
    SysDictEnum         dictEnum;
    int                 i, enumCount;
    Set                 removeValues;
    ;
    removeValues = new Set(Types::String);
    // A set with the values that have to be removed
 removeValues.add("Department");
    removeValues.add("Purpose");
    dictEnum = new SysDictEnum(enumNum(SysDimension));
    enumCount = dictEnum.values();
    super(_dialog);
    formRun = _dialog.formRun();
 // Get the combo box control's instance
    formComboBoxControl = formRun.design().controlName(dimension.name());
    
 // Clear all the combo box items.
 formComboBoxControl.clear();
    for (i=0; i<enumCount; i++)
    {
  // If the current enum element is present in the set of elements to be removed,
  // dont bother adding it to the combobox.
        if (removeValues.in(dictEnum.index2Label(i)))
        {
            continue;
        }
        formComboBoxControl.add(dictEnum.index2Label(i));
    }

 // Select the first item in the combo box.
    formComboBoxControl.selection(0);
}
That is it. Run the dialog now and you will only see Cost center in the dialog.

But this solution isnt complete yet. You may be wondering why? Well, try to get the value of the combo box. You will end up getting wrong index values.

The reason for this is that when we added the combo box control onto the for, we specified SysDimension as the typeId. So the kernel will always tro to return an element from thisenum based on the selected index. Since in our case, we have only one element in our combo box, i.e., Cost center, the return index is zero (indexes are zero based). But zero is the value of Department in SysDimension and that is what the user will get.
So to fix this issue, we need to first store the values being added in the combo box and the actual values compared to the SysDimension enum in a map. A map is a key-value pair container and is suited for our purpose here.
Update the code in the dialogPostRun method as shown below.
public void dialogPostRun(DialogRunbase _dialog)
{
    FormRun             formRun;
    SysDictEnum         dictEnum;
    int                 i, j, enumCount;
    Set                 removeValues;
    ;
    removeValues = new Set(Types::String);
    // A set with the values that have to be removed
 removeValues.add("Department");
    removeValues.add("Purpose");
// Add this line to initialize the map to store the correct enum values.
    dimensionAcceptedValues = new Map(Types::Integer, Types::Enum);
    dictEnum = new SysDictEnum(enumNum(SysDimension));
    enumCount = dictEnum.values();
    super(_dialog);
    formRun = _dialog.formRun();
 // Get the combo box control's instance
    formComboBoxControl = formRun.design().controlName(dimension.name());
    
 // Clear all the combo box items.
 formComboBoxControl.clear();
    for (i=0; i<enumCount; i++)
    {
  // If the current enum element is present in the set of elements to be removed,
  // dont bother adding it to the combobox.
        if (removeValues.in(dictEnum.index2Label(i)))
        {
            continue;
        }
        formComboBoxControl.add(dictEnum.index2Label(i));
// Add this line to store the correct enum value
        dimensionAcceptedValues.insert(j, dictEnum.index2Value(i));
        j++;
    }

 // Select the first item in the combo box.
    formComboBoxControl.selection(0);
}

Declare a map object named dimensionAcceptedValues in the classDeclaration.

Now add this code in getFromDialog() method

public boolean getFromDialog()
{
    SysDictEnum     dictEnum;
    boolean ret;
    ret = super();
    dictEnum = new SysDictEnum(enumNum(SysDimension));
    info(strfmt("You selected %1",dictEnum.index2Label(dimensionAcceptedValues.lookup(formComboBoxControl.selection()))));
    return ret;
}
Run the class and press the OK button. See if you get the correct result. Test it with some other enum to see if it is working as expected.

I hope this post was helpful. You can donwload the xpo for the project from here.

Thats all for today. Do check back again as we continue to learn.

Popular posts from this blog

How to add empty ranges in query

Get selected records in Dynamics AX 2012

How to refer to form controls in code without setting the AutoDeclaration property in Dynamics AX?