Blog

Name is Anant Dubey and the intent to create this blog is to discuss the problems and issues that developer face in the dynamics AX development and to share the new things that come up with the new version of AX.

Tuesday, September 5, 2023

override lookup method in Event handler and chain of command in d365fo

 link - https://dynamics365musings.com/override-an-existing-lookup-method-chain-of-command/


Two Ways To Override An Existing Lookup Method

There are actually two ways to override an existing lookup method.

I will explain both methods. No pun intended. Ultimately, I do not know that one way is preferred over the other. I am more partial to using Chain Of Command, because I find the attribute syntax easier to write. And I tend to put all of my other extension code in a Chain Of Command class. But please use whatever you are most comfortable with.

If you are new to Chain Of Command, I recommend you read this previous article on Chain Of Command Fundamentals.

The Example Scenario

In this section, consider the example that you want to override an existing lookup method on the customer details form. Go to customer form by searching for ‘all customers’ in the search bar. Then select a customer to open the customer details form.

The CustTable form, contains a field that lets a user select the customer group. By default this lookup method shows two columns. The customer group ID and the Description.

Let’s pretend we wish to show a third column. The related Customer Group form contains a field named ‘Terms of payment’. In this example, I will show you how to display additional columns in the lookup.

Override An Existing Lookup Using An Event Handler

In this previous article I showed you how you can use a form event handler to override an existing lookup. The key in this situation, is to use CancelSuperCall.

class TutorialCustTable_Form_Handler
{
    /// <summary>
    ///
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    [FormControlEventHandler(formControlStr(CustTable, Posting_CustGroup), FormControlEventType::Lookup)]
    public static void Posting_CustGroup_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(CustGroup), sender);
        
        // Add the lookup columns
        sysTableLookup.addLookupfield(fieldNum(CustGroup, CustGroup));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, Name));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, PaymTermId));

        // Run the lookup
        sysTableLookup.performFormLookup();

        //cancel the call to super() to prevent the system from trying to show 
        //the lookup form twice and cause an error.
        FormControlCancelableSuperEventArgs cancelableSuperEventArgs = e as FormControlCancelableSuperEventArgs;
        cancelableSuperEventArgs.CancelSuperCall();
    }
}

Override An Existing Lookup Using Chain Of Command

Secondly, we will look at how to override an existing lookup using Chain Of Command. Create a new class, by right clicking on the project and select Add>Class. Name the class TutorialCustTable_Form_Extension.

Now that the class is created, we need to add the attribute to above the class definition to indicate to the compiler that code in this class extends the code in the form CustTable. See this article for how to use chain of command on form methods. Your code should look like this to start.

[ExtensionOf(formStr(CustTable))]
final class TutorialCustTable_Form_Extension
{
}

You may think that we need to add a chain of command class for the form control. However, in this case, we actually need to add form methods. Specifically, add an ‘init’ method and a lookup method. First, we will create a lookup method. And then the ‘init’ method, which gets called when the form first opens, will register our version of the lookup method.

First, add the lookup method. In this case, this is just a method that takes a form control object. It can actually be named something other than just ‘lookup’.

[ExtensionOf(formStr(CustTable))]
final class TutorialCustTable_Form_Extension
{
    public void overridenCustGroupLookup(FormStringControl _formControl)
    {
        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(CustGroup), _formControl);

        // Add the lookup columns
        sysTableLookup.addLookupfield(fieldNum(CustGroup, CustGroup));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, Name));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, PaymTermId));

        // Run the lookup
        sysTableLookup.performFormLookup();
    }

}

Secondly, we need to extend the ‘init’ method to add code that will register the lookup method we just created and associate to the correct form control. The complete code should look like this.

[ExtensionOf(formStr(CustTable))]
final class TutorialCustTable_Form_Extension
{
    public void init()
    {
        next init();

        Posting_CustGroup.registerOverrideMethod(methodStr(FormDataObject, lookup), formMethodStr(CustTable, overridenCustGroupLookup));
    }

    public void overridenCustGroupLookup(FormStringControl _formControl)
    {
        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(CustGroup), _formControl);

        // Add the lookup columns
        sysTableLookup.addLookupfield(fieldNum(CustGroup, CustGroup));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, Name));
        sysTableLookup.addLookupfield(fieldNum(CustGroup, PaymTermId));

        // Run the lookup
        sysTableLookup.performFormLookup();
    }
}

In our example, the form control we needed to change the lookup for, had the ‘Auto Declaration’ property set to Yes. This meant we could simply use the name of the control, Posting_CustGroup, in our code. However, that is not always the case. If you need to reference a control that does not have this property set, you can find the control by adding an extra line of code. You still need to reference the control’s name. But this code still works even when the code does not have the ‘Auto Declaration’ property set to Yes. The ‘init’ method would then look like this.

public void init()
    {
        next init();

        FormStringControl custGroupControl = this.design().controlName(formControlStr(CustTable, Posting_CustGroup));
        custGroupControl.registerOverrideMethod(methodStr(FormDataObject, lookup), formMethodStr(CustTable, overridenCustGroupLookup));
    }

The method named registerOverrideMethod will tell the system what method to use as the lookup code for this form.

Demonstration

After adding all the code, save and compile your project.

In order to see your latest changes, reload the customer details form in your browser.

Finally, test out the overridden lookup method. You show now see all three columns showing in the lookup.

Override lookup method in d365fo

 

Override Lookup AX7 & D365FO



Here is the small example to override lookup ..


copy the lookup event handler of the field and  paste the event into any class




/// <summary>
    ///
    /// </summary>
    /// <param name="sender">receiving value in parameter</param>
    /// <param name="e">receiving value in parameter</param>
    [FormControlEventHandler(formControlStr(PayrollEmployerTaxRegion, Overview_StateId), FormControlEventType::Lookup)]
    public static void Overview_StateId_OnLookup(FormControl sender, FormControlEventArgs e)
    {
           /// write your lookup code here

if control or field already have lookup to we need to cancel parent lookup execution otherwise we will get exception.

below code you can use to cancel parent lookup ---
        FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;
        //cancel super() to prevent error.
        ce.CancelSuperCall();
      }


Here is the complete code sample 


/// <summary>
    ///
    /// </summary>
    /// <param name="sender">receiving value in parameter</param>
    /// <param name="e">receiving value in parameter</param>
    [FormControlEventHandler(formControlStr(PayrollEmployerTaxRegion, Overview_StateId), FormControlEventType::Lookup)]
    public static void Overview_StateId_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(LogisticsAddressState), sender);
        Query               query           = new Query();

        // Filter lookup to only show US states
        query.addDataSource(tableNum(LogisticsAddressState)).addRange(fieldNum(LogisticsAddressState, CountryRegionId)).value(LogisticsAddressCountryRegion::findByISOCode(SysCountryRegionCode::countryInfo(curext())).CountryRegionId);

        // Sort the lookup by state Id
        query.dataSourceTable(tableNum(LogisticsAddressState)).addOrderByField(fieldNum(LogisticsAddressState, StateId), SortOrder::Ascending);

        // Add fields
        sysTableLookup.addLookupfield(fieldNum(LogisticsAddressState, StateId));
        sysTableLookup.addLookupfield(fieldNum(LogisticsAddressState, Name));

        // Run lookup
        sysTableLookup.parmQuery(query);
        sysTableLookup.performFormLookup();
        FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;

        //cancel super() to prevent error.
        ce.CancelSuperCall();
    }


ref: - https://community.dynamics.com/blogs/post/?postid=c7132ede-dd1b-4408-a038-4354f0a2c7be