Thursday 12 March 2020

Form & Table Event Handlers

Form data source event handler

 [FormDataSourceEventHandler(formDataSourceStr(EcoResProductDetailsExtended, InventTable), FormDataSourceEventType::Written)]
public static void InventTable_OnWritten(FormDataSource sender, FormDataSourceEventArgs e){
    FormRun                 form           = sender.formRun();
    FormDataSource          InventTable_ds =       form.dataSource(formDataSourceStr(EcoResProductDetailsExtended,InventTable)) as FormDataSource;
   InventTable             inventTable    = InventTable_ds.cursor();
}

Form event handler Table Buffer on form closing event

[FormEventHandler(formStr(EcoResAttributeValue), FormEventType::Closing)]
public static void EcoResAttributeValue_OnClosing(xFormRun sender, FormEventArgs e)
{
     FormDataSource ecoResProduct_ds   =          sender.dataSource(formDataSourceStr(EcoResAttributeValue, EcoResProductAttributeValue));
      EcoResProductAttributeValue      ecoResAttributeValue = ecoResProduct_ds.cursor();
}   
Control value and form event level for which auto declaration must be set true

[FormControlEventHandler(formControlStr(EcoResProductCreate, OKButton), FormControlEventType::Clicked)]
public static void OKButton_OnClicked(FormControl sender, FormControlEventArgs e)
{
       FormRun             element       = sender.formRun();
       //form control
       FormControl         modelGroupRef = element.design(0).controlName("ModelGroupId");
        Info(strfmt(“Model Group %1”, modelGroupRef.valueStr()));
       //form parameter
       ItemId              itemId        = element.parmItemId();
}

Post handler for class method

[PostHandlerFor(classStr(EcoResProductReleaseManager), methodStr(EcoResProductReleaseManager, release))]
public static void EcoResProductReleaseManager_Post_release(XppPrePostArgs args){
     EcoResProductReleaseManager releaseMgr;
    //Getting the class object
    releaseMgr     = args.getThis();
   //Getting the class parameter
   ItemId itemId  = releaseMgr.parmItemId();
   //Getting the method argument
    boolean itemCreation = args.getArg("_isCreation");
}

Post handler for overriding table methods modified field and validate Write

[PostHandlerFor(tableStr(InventTable), tableMethodStr(InventTable, validateWrite))]
public static void InventTable_Post_validateWrite(XppPrePostArgs args)
{
      InventTable inventTable = args.getThis() as InventTable
      boolean ret = true;
      // Override the validations here and set the return value accordingly.
       Args.setReturnValue(ret);
}

[PostHandlerFor(tableStr(InventTable), tableMethodStr(InventTable, modifiedField))]
public static void InventTable_Post_modifiedField(XppPrePostArgs args)
{
        //Getting the table buffer
        InventTable inventTable = args.getThis() as InventTable
       //Getting the field id method argument.
        FieldId fieldModified = args.getArg("_fieldId");
        switch (fieldModified)
        {
            //Here you can write your logic on modified field method
                break;
        }
}
1. Form dataSource event handler:  will be using the vendTable form to get table buffer and perform additional business logic or validation.
Vendtable = Form namevendTable = form data source name
[FormDataSourceEventHandler(formDataSourceStr(VendtablevendTable), FormDataSourceEventType::Written)]
public static void vendTable_OnWritten(FormDataSource sender, FormDataSourceEventArgs e)
{
    FormRun                 form           = sender.formRun();
    FormDataSource          vendTable_ds =       form.dataSource(formDataSourceStr(Vendtable,Vendtable)) as FormDataSource;
   Vendtable     Vendtable= vendTable_ds.cursor();
<Now to got table buffer, perform business logic/validation>
}
lets see one more example below;

2. Form DataSource while closing the form (same will apply for OnInitialized,
[FormEventHandler(formStr(EcoResAttributeValue), FormEventType::Closing)]
public static void EcoResAttributeValue_OnClosing(xFormRun sender, FormEventArgs e)
{
     FormDataSource ecoResProduct_ds   =          sender.dataSource(formDataSourceStr(EcoResAttributeValue, EcoResProductAttributeValue));
      EcoResProductAttributeValue      ecoResAttributeValue = ecoResProduct_ds.cursor();
<YOUR CODE>
}   

3.  Post-event hander of Form init or any other standard method method
[[PostHandlerFor(formStr(Ledger), formMethodStr(Ledger, init))]
    public static void Ledger_Post_init(XppPrePostArgs _args)
    {
        #ISOCountryRegionCodes
        FormRun form = _args.getThis();
        FormDesign design = form.design();
        FormControl revaluationAccount = design.controlName(formControlStr(Ledger, revaluationAccount));
        FormControl currencyRevaluation = design.controlName(formControlStr(Ledger, currencyRevaluation));

<your code>
}

4. Form control event hander:
[FormControlEventHandler(formControlStr(LogisticsPostalAddress, Roles), FormControlEventType::Modified)]
    public static void Roles_OnModified(FormControl sender, FormControlEventArgs e)
    {
        FormRun element = sender.formRun();
        FormControl purposeCtrl   = element.design().controlName(formControlStr(LogisticsPostalAddress, Roles));
   
        FormDataSource logisticsLocation_DS = element.dataSource(formDataSourceStr(LogisticsPostalAddress, LogisticsLocation));
       <business logic>
    }


Table Event Handlers:  OnValidateField
[DataEventHandler(tableStr(CustTable), DataEventType::ValidatedField)]

public static void CustTable_onValidatedField(Common sender, DataEventArgs e)
{
ValidateFieldEventArgs  event = e as ValidateFieldEventArgs ;
CustTable custTable = sender as CustTable;
boolean result = event.parmValidateResult();
result = result && RegNumberValidator_BG::validate(custTable.AccountNum, custTable.RegistrationNumber_BG, CustVendACType::Cust);
event.parmValidateResult(result);
}

Table Event Handlers:  OnValidateField
[DataEventHandler(tableStr(InventLocation), DataEventType::ValidatedField)]
public static void InventLocation_onValidatedField(Common sender, DataEventArgs e)
{
InventLocation inventLocation = sender as InventLocation;
ValidateFieldEventArgs fieldArgs = e;
boolean ret;
InventLocation inventLocationLoc;
switch(fieldArgs.parmFieldId())
{
case fieldNum(InventLocation, field1):
if(inventLocation.MyWorkerAssociate != '')
{
<Your code/ business ogic/validation>
<ret = true or false>
fieldArgs.parmValidateResult(ret);
}
}
}

Table Event Handlers:  ModifiedField

[DataEventHandler(tableStr(PurchAgreementHeader), DataEventType::ModifiedField)]
public static void PurchAgreementHeader_onModifiedField(Common sender, DataEventArgs e)
{
ModifyFieldEventArgs    event = e as DataEventArgs;
PurchAgreementHeader    purchAgreementHeader = sender as PurchAgreementHeader;
FieldId                 fieldId = event.parmFieldId();
date                    emptyDate;
switch(fieldId)
{
case fieldNum(PurchAgreementHeader, BankGuarantee):
if(purchAgreementHeader.BankGuarantee == NoYes::No)
{
purchAgreementHeader.BankGuaranteeExpirationDate = emptyDate ;
purchAgreementHeader.BankGuaranteeNumber         = “”;
purchAgreementHeader.Bank                        = “”;
}
break;
}
}



*********************Form Event Handlers*************************************
[FormEventHandler(formStr(HcmPosition), FormEventType::Initialized)]
        public static void HcmPosition_OnInitialized(xFormRun sender, FormEventArgs e)
        {

            FormDataSource hcmosition_ds = sender.dataSource(formDataSourceStr(HcmPosition, HcmPosition));
 Or 
FormDataSource                              hcmosition_ds = sender.dataSource('HcmPosition');
        }

If you copy form datasource event you can get form run object from datasource  as below. Once you get form run you can call any form method available on the form.
[FormDataSourceEventHandler(formDataSourceStr(HcmPosition, HcmPosition), FormDataSourceEventType::Created)]
        public static void HcmPosition_OnCreated(FormDataSource sender, FormDataSourceEventArgs e)
        {

            FormRun formRun = sender.formRun() as FormRun;
            
        }

Similarly you can get formrun on a from control event handler using FormControl
[FormControlEventHandler(formControlStr(HcmPosition, HcmPosition_PositionId1), FormControlEventType::Modified)]
        public static void HcmPosition_PositionId1_OnModified(FormControl sender, FormControlEventArgs e)
        {
            FormRun formRun = sender.formRun() as FormRun;

        }
To get control on a form  and make it editable or non-editable
[FormEventHandler(formStr(HcmPosition), FormEventType::Initialized)]
        public static void HcmPosition_OnInitialized(xFormRun sender, FormEventArgs e)
        {
            sender.design().controlName(formControlStr(HcmPosition, HcmPositionNewPosition)).AllowEdit(false);
            // to get form open Mode
            OpenMode                                    openMode = sender.args().openMode();
        }

Getting  current record
Hcmposition is first datasource  on HcmPosition form  that’s why  gave 1 in datasource.
[FormControlEventHandler(formControlStr(HcmPosition, HcmPositionNewPosition), FormControlEventType::Clicked)]
        public static void HcmPositionNewPosition_OnClicked(FormControl sender, FormControlEventArgs e)
        {

            HcmPosition hcmposition = sender.formRun().dataSource(1).cursor();
        }

Using DataEventArgs to send Validation result
[DataEventHandler(tableStr(CategoryTable), DataEventType::ValidatingDelete)]
    public static void CategoryTable_onValidatingDelete(Common _sender, DataEventArgs _e)
    {
        CategoryTable categoryTable = _sender as CategoryTable;
        ValidateEventArgs validateEventArgs = _e as ValidateEventArgs;
        boolean ret = true;

        if (categoryTable.UseInProject)
        {
            ProjCategory projCategory = ProjCategory::find(categoryTable.CategoryId);
            ret = projCategory.validateDelete();
        }

        if (ret && categoryTable.UseInExpense)
        {
            TrvCostType trvCostType = TrvCostType::find(categoryTable.CategoryId);
            ret = trvCostType.validateDelete();
        }
        
        if (!ret)
        {
            validateEventArgs.parmValidateResult(false);
        }
    }

Similarly you can use on ValidateFieldValueEventArgs  to send validation result back to Validate Field method
[DataEventHandler(tableStr(LedgerParameters), DataEventType::ValidatingFieldValue)]
    public static void LedgerParameters_onValidatingFieldValue(Common sender, DataEventArgs e)
    {
        ValidateFieldValueEventArgs ve = e;
        boolean isValid = true;
        LedgerParameters ledgerParameters = sender as LedgerParameters;
        #isoCountryRegionCodes
        
        if (ve.parmFieldName() == fieldStr(LedgerParameters, ChineseVoucher_CN) 
            && SysCountryRegionCode::isLegalEntityInCountryRegion([#isoCN]))
        {
            if ((select firstonly RecId from LedgerJournalTrans
                    where LedgerJournalTrans.LedgerVoucherType_CN != 0
                        || LedgerJournalTrans.Voucher_CN != '').RecId != 0)
            {
                // The general journal needs to be empty in order to modify the setup for the Chinese voucher system.
                isValid = checkFailed("@GLS54497");
            }
            ve.parmValidateResult(isValid);
        }
        
    }


Reference : https://community.dynamics.com/365/financeandoperations/b/365operationswithsukrut/posts/customizing-d365-with-event-handlers

No comments:

Post a Comment

POSTMAN D365

  Postman is useful to test the behavior of different OData class from/to D365FO. In this post we will see the steps to setup Postman with D...