Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны Забыли пароль?

Опции темы Поиск в этой теме Опции просмотра
Старый 16.12.2016, 18:12   #1  
Blog bot is offline
Blog bot
14,195 / 616 (49) +++++++
Регистрация: 28.10.2006
goshoom: Extensible control – X++ classes

User interface in AX 7 (Dynamics 365 for Operations) is now in web browser, which forced Microsoft to make many fundamental changes. Obviously, they had to rewrite all controls to HTML (plus JavaScript and CSS), but it has many additional consequences. For example, it’s not possible anymore to run X++ code on client; all X++ code runs on server. If something happens in browser, such as you click a button, the browser can still call X++ code on server, but the call over internet is quite slow. Another option is running client-side logic written in JavaScript. In either case, it’s quite different from how older versions of AX worked. On the other hand, it all gives us a plenty of new options.

AX developers usually don’t have to care about any HTML, JavaScript and so on; they deal with controls (such as buttons and grids), both in designer and in X++ code. The whole rendering to HTML, client scripting, communication with server and so on is done by controls themselves, with the help of AX kernel.

That you don’t usually have to care about how control work doesn’t mean that it isn’t useful. It can help you with debugging and exploring capabilities of existing controls, but most importantly it allows you to design new controls for your particular requirements. This is extremely powerful and it’s not too complicated either. Of course, you must know something about HTML and JavaScript, and you’ll find that designing a control that works great in all cases (small resolution, right-to-left languages etc.) isn’t completely trivial, but don’t bother about it right now.

Let’s build a simple control showing a map for given coordinates. I’m not going to dive into much details, explain all capabilities and so on; I want to show a case from beginning to end without any distractions. If you want to build a more useful control, you’ll still have to go to documentation and learn about additional features from there.

First of all, we need a so-called “build class”, which defines how the control behaves at design time in Visual Studio.

Create an X++ class called MyMapControlBuild and paste the following code there:

[FormDesignControlAttribute("My map")]class MyMapControlBuild extends FormBuildControl{ real latitude; real longitude; int zoom; [FormDesignPropertyAttribute("Latitude", "Map")] public real parmLatitude(real _latitude = latitude) { if (!prmIsDefault(_latitude)) { latitude = _latitude; } return latitude; } [FormDesignPropertyAttribute("Longitude", "Map")] public real parmLongitude(real _longitude = longitude) { if (!prmIsDefault(_longitude)) { longitude = _longitude; } return longitude; } [FormDesignPropertyAttribute("Zoom", "Map")] public int parmZoom(int _zoom = zoom) { if (!prmIsDefault(_zoom)) { zoom = _zoom; } return zoom; }}

The class inherits from FormBuildControl and has an attribute defining its human-friendly name. It also contains three fields (latitude, longitude and zoom) and corresponding parm* methods, each decorated with FormDesignPropertyAttribute. We’ll see these three properties in the form designer; we’ll be able to set their values and later we’ll use them to show something on the map.

The second argument of FormDesignPropertyAttribute is the category of properties, which seems to be ignored in the moment (but I still think you should use it; hopefully it will become supported later).

Then we need one more class, a so-called “runtime class”. It represents the X++ part of the actual control when rendered in user interface. You could put more logic there, but in this case, we’ll only expose our properties.

Let’s do it in a few steps. Create a new class, MyMapControl, with the following code.

[FormControlAttribute('MyMap', '', classstr(MyMapControlBuild))]class MyMapControl extends FormTemplateControl{ public void new(FormBuildControl _build, FormRun _formRun) { super(_build, _formRun); this.setTemplateId('MyMap'); this.setResourceBundleName('/resources/html/MyMap'); }}

Create three FormProperty variables.

FormProperty latitude;FormProperty longitude;FormProperty zoom;

For each property, add a parm* method decorated with FormPropertyAttribute. These properties will be available in JavaScript in browser.

[FormPropertyAttribute(FormPropertyKind::Value, "Latitude")]public real parmLatitude(real _value = latitude.parmValue()){ if (!prmIsDefault(_value)) { latitude.setValueOrBinding(_value); } return latitude.parmValue();} [FormPropertyAttribute(FormPropertyKind::Value, "Longitude")]public real parmLongitude(real _value = longitude.parmValue()){ if (!prmIsDefault(_value)) { longitude.setValueOrBinding(_value); } return longitude.parmValue();} [FormPropertyAttribute(FormPropertyKind::Value, "Zoom")]public int parmZoom(int _value = zoom.parmValue()){ if (!prmIsDefault(_value)) { zoom.setValueOrBinding(_value); } return zoom.parmValue();}

We also need to initialize FormProperty objects and associate them with parm* methods. Put this code to the constructor, below super().

latitude = properties.addProperty(methodStr(MyMapControl, parmLatitude), Types::Real);longitude = properties.addProperty(methodStr(MyMapControl, parmLongitude), Types::Real);zoom = properties.addProperty(methodStr(MyMapControl, parmZoom), Types::Integer);

The last missing piece is the initialization of the control from the build class. We take values of designer properties and put them into our actual control.

public void applyBuild(){ super(); MyMapControlBuild build =; if (build) { this.parmLatitude(build.parmLatitude()); this.parmLongitude(build.parmLongitude()); this.parmZoom(build.parmZoom()); } }

Here is the complete class, so you can easily copy and paste the code.

[FormControlAttribute('MyMap', '', classstr(MyMapControlBuild))]class MyMapControl extends FormTemplateControl{ FormProperty latitude; FormProperty longitude; FormProperty zoom; public void new(FormBuildControl _build, FormRun _formRun) { super(_build, _formRun); this.setTemplateId('MyMap'); this.setResourceBundleName('/resources/html/MyMap'); latitude = properties.addProperty(methodStr(MyMapControl, parmLatitude), Types::Real); longitude = properties.addProperty(methodStr(MyMapControl, parmLongitude), Types::Real); zoom = properties.addProperty(methodStr(MyMapControl, parmZoom), Types::Integer); } public void applyBuild() { super(); MyMapControlBuild build =; if (build) { this.parmLatitude(build.parmLatitude()); this.parmLongitude(build.parmLongitude()); this.parmZoom(build.parmZoom()); } } [FormPropertyAttribute(FormPropertyKind::Value, "Latitude")] public real parmLatitude(real _value = latitude.parmValue()) { if (!prmIsDefault(_value)) { latitude.setValueOrBinding(_value); } return latitude.parmValue(); } [FormPropertyAttribute(FormPropertyKind::Value, "Longitude")] public real parmLongitude(real _value = longitude.parmValue()) { if (!prmIsDefault(_value)) { longitude.setValueOrBinding(_value); } return longitude.parmValue(); } [FormPropertyAttribute(FormPropertyKind::Value, "Zoom")] public int parmZoom(int _value = zoom.parmValue()) { if (!prmIsDefault(_value)) { zoom.setValueOrBinding(_value); } return zoom.parmValue(); }}

Build the solution, create a new form and add the new control, My map (the name comes from FormDesignControlAttribute).

We can’t successfully run the form yet, because we still haven’t defined how the control should render, but we can work with the control in designer, set its properties, possibly override its methods and so on.

If you open properties, you’ll see our three custom properties (Latitude, Longitude and Zoom), together with many other properties common to all controls (such as Visible). I would expect to see a new group of properties, Map, but it’s not how it works in the moment.

Fill in your favorite GPS coordinates, a zoom level and the required size of the control.

This is all for now, we’ll add HTML and JavaScript in the next blog post.

Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
За это сообщение автора поблагодарили: Diman (1).

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
goshoom: Extensible control – HTML/JavaScript Blog bot DAX Blogs 0 16.12.2016 18:12
goshoom: Locking in Team Foundation Version Control Blog bot DAX Blogs 0 15.10.2014 22:11
emeadaxsupport: SEPA affected objects Blog bot DAX Blogs 0 29.11.2013 13:11
Axilicious:Hosting custom WPF calendar control in AX 2012 Blog bot DAX Blogs 0 20.05.2013 18:11
Передача функции в качестве параметра lemchey_white DAX: Программирование 20 21.01.2008 22:51
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Часовой пояс GMT +3, время: 22:12.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.