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

Опции темы Поиск в этой теме Опции просмотра
Старый 04.04.2018, 01:13   #1  
Blog bot is offline
Blog bot
25,526 / 847 (80) +++++++
Регистрация: 28.10.2006
stoneridgesoftware: Learn to Use a Label Creator Add-in Extension in Dynamics 365 for Finance & Operations

Creating labels has always been considered a chore by developers, and the task hasn’t really gotten any easier with Dynamics 365. Wouldn’t it be nice if you could type your value into the property and let Visual Studio move it to a label file? Luckily, we can. I’ll show you how to use the label creator Add-in extension in Dynamics 365 for Finance & Operations.

Start by creating a new Dynamics 365 Developer Tools Add-in project.

This will create a new class library project that contains two source files. The first, DesignerContextMenuAddIn.cs, contains boilerplate code for creating a designer add-in. The second, MainMenuAddIn.cs, contains a menu add-in.

The first thing we will need to do is to add a few references to our project:
  • C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\PublicAssemblies\
    • EnvDTE.dll
    • EnvDTE80.dll
  • C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\5hutepyf.xp2\
    (Your folder may vary slightly)</p>
    • Microsoft.Dynamics.Framework.Tools.LabelEditor.dll
    • Microsoft.Dynamics.Framework.Tools.ProjectSystem.dll
    • Microsoft.Dynamics.Framework.Tools.ProjectSupport.dll
  • C:\AOSService\PackagesLocalDirectory\bin\
    • Microsoft.Dynamics.AX.Metadata.dll
    • Microsoft.Dynamics.Framework.Tools.AutomationObjects.dll
Our designer’s context menu is controlled by the DesignerMenuExportMetadata attribute on the class. You can see in the screenshot that by default our add-in will appear in both the Form and Table designers.

The OnClick method is called when the user clicks on our menu. We will modify this method to convert the text contained in the Label property to an actual label. To do this, create regular expression to distinguish between a label identifier and a normal string.

private static Regex newLabelMatcher = new Regex("\\A(?\\@)(?[a-zA-Z]\\w*):(?[a-zA-Z]\\w*)", RegexOptions.Compiled | RegexOptions.CultureInvariant); private static Regex legacyLabelMatcher = new Regex("\\A(?(?\\@)(?[a-zA-Z][a-zA-Z][a-zA-Z])\\d+)", RegexOptions.Compiled | RegexOptions.CultureInvariant);These expressions will be used by the following methods.private Boolean IsValidLabelId(String labelId){ bool result = false; if (String.IsNullOrEmpty(labelId) == false) { result = DesignerContextMenuAddIn.IsLegacyLabelId(labelId); if (result == false) { result = (DesignerContextMenuAddIn.newLabelMatcher.Matches(labelId).Count > 0); } } return result;} private static Boolean IsLegacyLabelId(String labelId){ bool result = false; if (String.IsNullOrEmpty(labelId) == false) { result = (DesignerContextMenuAddIn.legacyLabelMatcher.Matches(labelId).Count > 0); } return result;}Handle the click event in the OnClick method. Here we will test the selected object, get the object’s model and label file, and create the label.public override void OnClick(AddinDesignerEventArgs e){ ModelInfoCollection modelInfoCollection = null; IMetaModelService metaModelService = null; // Get the metamodel provider IMetaModelProviders metaModelProvider = ServiceLocator.GetService(typeof(IMetaModelProviders)) as IMetaModelProviders; if (metaModelProvider != null) { // Get the metamodel service metaModelService = metaModelProvider.CurrentMetaModelService; } try { // Is the selected element a table? if (e.SelectedElement is ITable) { ITable table = e.SelectedElement as ITable; modelInfoCollection = metaModelService.GetTableModelInfo(table.Name); AxLabelFile labelFile = this.GetLabelFile(metaModelProvider, metaModelService, modelInfoCollection); this.createLabel(table, labelFile); } } catch (Exception ex) { CoreUtility.HandleExceptionWithErrorMessage(ex); }}private AxLabelFile GetLabelFile(IMetaModelProviders metaModelProviders, IMetaModelService metaModelService, ModelInfoCollection modelInfoCollection){ // Choose the first model in the collection ModelInfo modelInfo = ((System.Collections.ObjectModel.Collection)modelInfoCollection)[0]; // Construct a ModelLoadInfo ModelLoadInfo modelLoadInfo = new ModelLoadInfo { Id = modelInfo.Id, Layer = modelInfo.Layer, }; // Get the list of label files from that model IList labelFileNames = metaModelProviders.CurrentMetadataProvider.LabelFiles.ListObjectsForModel(modelInfo.Name); // Choose the first // What happens if there is no label file? AxLabelFile labelFile = metaModelService.GetLabelFile(labelFileNames[0], modelLoadInfo); return labelFile;} private void createLabel(ITable table, AxLabelFile labelFile){ if (this.IsValidLabelId(table.Label) == false) { table.Label = this.FindOrCreateLabel(table.Label, table.Name, "Label", labelFile); } if (this.IsValidLabelId(table.DeveloperDocumentation) == false) { table.DeveloperDocumentation = this.FindOrCreateLabel(table.DeveloperDocumentation, table.Name, "DeveloperDocumentation", labelFile); }} private String FindOrCreateLabel(String labelText, String elementName, String propertyName, AxLabelFile labelFile){ string newLabelId = String.Empty; // Don't bother if the string is empty if (String.IsNullOrEmpty(labelText) == false) { // Construct a label id that will be unique string labelId = $"{elementName}{propertyName}"; // Get the label factor LabelControllerFactory factory = new LabelControllerFactory(); // Get the label edit controller LabelEditorController labelController = factory.GetOrCreateLabelController(labelFile, DesignerContextMenuAddIn.Context); // Make sure the label doesn't exist. // What will you do if it does? if (labelController.Exists(labelId) == false) { labelController.Insert(labelId, labelText, String.Empty); labelController.Save(); // Construct a label reference to go into the label property newLabelId = $"@{labelFile.LabelFileId}:{labelId}"; } } return newLabelId;}Lastly, open the resource file and change the DesignerAddinCaption. This value will appear in the context menu item.

To test your add-in, press F5 and Visual Studio will build your project and copy the dll to the appropriate folder. On my computer, the add-in folder is at C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\5hutepyf.xp2\AddinExtensions\.

Create a Dynamics 365 Unified Operations project.

Add a new table to the project.

Add a label file.

Open your table in the designer and type a value into the Label property.

Right-click the table node in the designer and move your mouse to the Add-ins menu.

Click the Create labels option and your add-in will create a label resource and update the Label property.

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

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
stoneridgesoftware: Setting Up Continuous Integrations in Dynamics 365 for Operations Blog bot DAX Blogs 0 29.09.2017 07:11
stoneridgesoftware: Setting Up Version Control in Dynamics 365 for Operations with Visual Studio Blog bot DAX Blogs 3 07.08.2017 11:35
stoneridgesoftware: Core Differences in Security Implementation between Dynamics AX and Dynamics 365 for Operations Blog bot DAX Blogs 0 01.04.2017 02:17
stoneridgesoftware: Five Things AX Developers Should Prepare for in Dynamics 365 for Operations Blog bot DAX Blogs 0 19.01.2017 20:11
crminthefield: Podcast and Overview: Microsoft Dynamics CRM 2011 Update Rollup 17 Blog bot Dynamics CRM: Blogs 0 10.05.2014 06:30
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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