mercredi 20 novembre 2013

Custom controls on Dynamics AX forms

What’s a ManagedHost ?

From the Microsoft Documentation:
The ManagedHost is a Microsoft Dynamics AX control that hosts a .NET control on a form. 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++. For information about CLR interop, see .NET Interop from X++. If you add more than one .NET control to a form, you also add a separate ManagedHost control for each .NET control.
A ManagedHost is a box that can hold any .NET user control.

For example, the controls that MorphX offers lack the Calendar control available among .NET controls
Using a custom user control, we can integrate a calendar in a usual Dynamics AX form.
The goal of this article will be to create a custom user control showing a calendar and enabling the user to populate the StringEdit field with the selected date (communication from .NET user control to AX control) and enabling setting the selected date from the StringEdit to the calendar (communication from AX user control to .NET).
These operations are the recurring interactions a developer will need to implement when integrating an external component to a form.

Create custom user controls

Custom user controls are created using the .NET framework (C#, VisualBasic, …) any DDL resulting from these languages could be used in the MorphX EDI, since X++, C# or VB all get translated to CIL.
Using a C# Visual Studio we create a WPF User Control Library containing a custom user control that will hold the Calendar control
The XAML code for this control is as simple as this:

<UserControl x:Class="SPLCalendarShowcase.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" >
    <Grid>
        <Calendar Height="170" Name="calendar1" Width="180" />
    </Grid>
</UserControl>

As a first step, we won’t implement any interaction between the control and X++, so there is no need to edit the C# code coming along with this user control.

Add the custom control as a ManagedHost

This step is made on the MorphX development environment.
When compiled this project result in a DLL file that should be copied into the folder
“C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin”
Then added as a reference in the AX project, the steps to add a reference are straightforward, you’ll need to specify the DDL file in from the folder : “C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin”
Then, we’ll need a form to show that component:
Then specify the control hosted by our ManagedHost:
The result of this is the following:

Two way communication between X++ and the ManagedHost

More than integrating a new control to a Dynamics AX Form, it would be interesting to enable a two ways interaction between the new user control and the Form:
  1.     The calendar changes a StringEdit value when a new date is selected (From the user control to AX )
  2.     The value of the StringEdit could be parsed as a date and automatically selected on the calendar (From AX to the user control)

From the user control to AX

The steps to enable this interaction are:
·         Adding and event to the control that would be launched when a new date is selected:
        public event EventHandler CalendarDateChanged;
        private void calendar1_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.CalendarDateChanged != null) this.CalendarDateChanged(sender, e);
        }
·         Connect to that event from AX by X++ code and refresh the StringEdit value:
Connect a listener to that event on form initialization – on the init() method :
public void init()
{
    super();
    calendarUserControl = ManagedHost.control();
    calendarUserControl.add_CalendarDateChanged(new ManagedEventHandler(this, 'Calendar_ValueChanged'));
}
The method Calendar_ValueChanged will handle the event like this:
void Calendar_ValueChanged(System.Object sender, System.Windows.RoutedEventArgs e)
{
    System.Windows.Controls.Calendar calendrier  = sender as System.Windows.Controls.Calendar;
    System.DateTime dt = calendrier.get_SelectedDate();
    str chaine = dt.ToString();
    StringEdit.text(chaine);
}

From AX to the user control

  • Create a method on the user control that changes the date on the calendar

        public void setCalendarDate(string dateString)
        {
            DateTime dt = DateTime.ParseExact(dateString, "dd/MM/yyyy HH:mm:ss", null);
            calendar1.SelectedDate = dt;
        }

  • Use this method from AX: on the clicked method of the button use the following code

void clicked()
{
    System.DateTime dt;
    super();
    calendarUserControl.setCalendarDate(StringEdit.text());
}

Notes:
  1. After these modifications on the user control, the new version should be compiled and recopied to the “C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin” folder.
  2. The copying may state that the DDL is in use and can’t be rewritten, try closing all the Dynamics AX (development env./client) windows. The retry while the AOS is stopped this should work.