ManagedHost control in Dynamics AX 2012

Friends,

Today, I would like to give a quick overview and an example of new ManagedHost control that has been introduced in AX 2012.

The ManagedHost is a Microsoft Dynamics AX control that hosts a .NET control on a form Actually, you can add and use Windows Presentation Foundation (WPF) or managed form controls. This was not available in DAX 2009.

The ManagedHost supports access to the properties, methods, and events of the specified .NET control. To provide access to these members of the .NET control, the ManagedHost uses the CLR interop feature of X++. [msdn]

Let me explain with a real quick example.

Create a new form and add a new ManagedHost control as shown below

ManagedHost

From the control selectors, select System.Windows.Forms and Button control as shown below and click on Ok Button

controller

Actually, I am trying to add a .NET button control and will invoke the events of the control from AX.

Then, Right click on the ManagedHost control and chose Events

events

From the list of events, select the click event and click on Add button as shown below

clik

Once you do this, you will automatically find that in the ClassDeclaration the control object is created.

public class FormRun extends ObjectRun

{

    System.Windows.Forms.Button _ManagedHost_Control;

 

}

Also, init() method will have the following code with the eventHandler.

  • You use the properties of the .NET control to configure that control or to obtain information from the control. To set a property value, assign a value to the set_<property name> property of the .NET control. To retrieve a value from a .NET control, use the get_<property name> property of the .NET control. [msdn]

I have added one line of code to set the button text as shown below

settext

Init() method – code below

public void init()

{

    super();

    _ManagedHost_Control = ManagedHost.control();

    _ManagedHost_Control.add_Click(new ManagedEventHandler(this, ‘ManagedHost_Click’));

 

    _ManagedHost_Control.set_Text("Open customer table");

}

 

When the button is clicked, ManagedHost_Click method gets triggered and I am just opening the customer table in the clicked event

void ManagedHost_Click(System.Object sender, System.EventArgs e)

{

    ;

    new SysTableBrowser().run(tableNum(CustTable));

}

 

If we open the events again, you will see that click event is mapped to AX X++ method “ManagedHost_Click” as shown below [just for your reference]

COMEBACK

We are done, Now right click on the form and chose Open.

You will see that .NET Button control is on your form with text “Open customer table” a shown below

buttonn

 

Click on the button and you should see the custTable opening in the TableBrowser.

image

You can try with other controls like Grid Views, progress bars, Calendar pickers or any other controls from the controller list, but I was unable to access some of the events/methods of .net controls in AX when I tried some [Chart control, Combo Box] .

hmm..Exploring more…will post soon.

For more details : http://msdn.microsoft.com/en-us/library/gg864879.aspx

Have a good weekend!

Thanks,

Happy Dax6ng.

Sreenath

Advertisements

Getting Segments from Segmented Entry control/Ledger dimension–Dynamics AX 2012 [X++]

Friends,

As you know, In AX 2012, we use the segmented entry control to associate an account and related financial dimensions with the record.

In our earlier posts, we have learnt about the segmented entry controls and in this post, we will see how to extract the segments from the segmented entry control.

Example : segmented control [Screen shot below]

sssegmented control

As you see that the above ledger dimension has the account associated with the segments[dimensions].

Below code will get all the account transactions [sum amount] group by CostCenter Dimension.

In the code, we will extract the segments with the help of DimensionStorage class

static void SR_Extract_SegmentName_values(Args _args)

{

    #define.CostCenter("CostCenter")

    Query                                   query;

    QueryRun                                queryRun;

    QueryBuildDataSource                    qbds,qbdsDate;

    GeneralJournalAccountEntry              generalJournalAccountEntry;

    GeneralJournalEntry                     generalJournalEntry;

    container                               value = conNull();

    OMOperatingUnit                         omou;

 

    // Dimension

    DimensionStorage        dimensionStorage;

 

    // Segment

    int                     segmentCount, segmentIndex;

    DimensionStorageSegment segment;

    str 100                 segmentName, MainAccount, segmentValue;

    container               segments;

    query                   = new Query();

    qbds                    = query.addDataSource(tableNum(GeneralJournalAccountEntry));

 

    // Sum functional and transaction amounts

 

    qbds.addSelectionField(fieldNum(GeneralJournalAccountEntry, AccountingCurrencyAmount), SelectionField::Sum);

    qbds.addSelectionField(fieldNum(GeneralJournalAccountEntry, TransactionCurrencyAmount), SelectionField::Sum);

    qbds.addGroupByField(fieldNum(GeneralJournalAccountEntry, LedgerDimension));

    qbdsDate = qbds.addDataSource(tableNum(GeneralJournalEntry));

    qbdsDate.joinMode(JoinMode::InnerJoin);

    qbdsDate.fetchMode(QueryFetchMode::One2One);

    qbdsDate.addLink(fieldNum(GeneralJournalAccountEntry, GeneralJournalEntry), fieldNum(GeneralJournalEntry, RecId));

    queryRun = new QueryRun(query);

 

    while (queryRun.next())

    {

        generalJournalAccountEntry = queryRun.get(tableNum(generalJournalAccountEntry));

        // Get dimension storage

        dimensionStorage = DimensionStorage::findById(GeneralJournalAccountEntry.LedgerDimension);

        if (dimensionStorage == null)

        {

            throw error("@SYS83964");

        }

        // Add segments for all hierarchies

        segments = conNull();

        // Get segments

        segmentCount = dimensionStorage.segmentCountForHierarchy(1);

        for (segmentIndex = 1; segmentIndex <= segmentCount; segmentIndex++)

        {

            // Get segment

            segment = dimensionStorage.getSegmentForHierarchy(1, segmentIndex);

            if (segment.parmDimensionAttributeValueId() != 0)

            {

                // Get segment name

                segmentName = DimensionAttribute::find(DimensionAttributeValue::find(segment.parmDimensionAttributeValueId        ()).DimensionAttribute).Name;

 

                // Add segment value

                segmentValue = segment.parmDisplayValue();

 

                if (segmentIndex == 1)

                {

                    MainAccount = segmentValue;

                }

 

                if (segmentName == #CostCenter)

                {

                   info("Main account – " +  MainAccount);

                   info("Segment Name – " + segmentName);

                   info("Cost center – "  + segmentValue);

                   info(strFmt(‘Total TransactionCurrency amount – %1’,generalJournalAccountEntry.TransactionCurrencyAmount));

                   info(strFmt(‘Total AccountingCurrency amount – %1’, generalJournalAccountEntry.AccountingCurrencyAmount));

                   info("______________________________________");

                }

            }

        }

    }

}

 

Below is the output

 

Output

[Note: In the above code , I have checked explicitly with the segment name to #CostCenter. There are many ways to find out whether the dimension belongs to Cost center/Department etc. we can use DimensionAttribute table to or OMOperatingUnit table to verify this]

If you want to restrict only linked main accounts as per the legal entity, you can use the below code

[I hope you know how the structure is >> Legal entity >> COA >> main accounts]

// Join to main account to filter by accounts

            qbds = query.dataSourceTable(tableNum(DimensionAttributeValueCombination));

            qbds = qbds.addDataSource(tableNum(MainAccount));

            qbds.fetchMode(QueryFetchMode::One2One);

            qbds.joinMode(JoinMode::InnerJoin);

            qbds.addLink(fieldNum(DimensionAttributeValueCombination, MainAccount), fieldNum(MainAccount, RecId));

 

            // Restrict to current COA and proper account types

            qbds.addRange(fieldNum(MainAccount, LedgerChartOfAccounts)).value(queryValue(LedgerChartOfAccounts::current()));

 

Happy Dax6ng,

Sreenath Reddy