You develop Microsoft Dynamics NAV Windows client control add-ins using the API that is defined in the Microsoft.Dynamics.Framework.UI.Extensibility assembly. A control add-in is defined as a class in a Visual C# solution. You can include more than one control add-in a single solution. When you have finished developing a control add-in, you build and sign an assembly before you install it on the computer that is running the Microsoft Dynamics NAV Windows client.

To create a control add-in, you need the following prerequisites:

To create the Microsoft Dynamics NAV Windows client control add-in

  1. In Visual Studio, create a Visual C# project type by using the Class Library template.

  2. In the project, add references to the following assemblies:

    • Microsoft.Dynamics.Framework.UI.Extensibility.dll assembly
      By default, the path of the assembly is C:\Program Files\Microsoft Dynamics NAV\71\RoleTailored Client. This reference is required for all control add-ins.
    • System.Windows.Forms
      Contains classes for creating user interfaces for Windows-based applications.

    Add additional references as required.

  3. Open the class.cs file and add the following using directives.

    C# Copy Code
    using Microsoft.Dynamics.Framework.UI.Extensibility;
    using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;
    using System.Windows.Forms;

    Add additional references as required.

  4. Declare a class for the control add-in that uses the Microsoft.Dynamics.Framework.UI.Extensibility.ControlAddInExportAttribute attribute. Derive the class from an abstract base class and implement the control add-in definition interface, as shown in the following examples.

    C# Copy Code
    [ControlAddInExport("MyCompany.MyProduct.MyAddin")]
    public class MyFieldPopupAddin : WinFormControlAddInBase, IObjectControlAddinDefinition

    C# Copy Code
    [ControlAddInExport("MyCompany.MyProduct.MyAddin")]
    public class MyFieldPopupAddin : StringControlAddInBase

    For information about the base classes and interfaces, see Client Extensibility API Overview.

    The Microsoft.Dynamics.Framework.UI.Extensibility.ControlAddInExportAttribute attribute declares the class in the assembly to be a control add-in that is identified by its Microsoft.Dynamics.Framework.UI.Extensibility.ControlAddInExportAttribute.Name property, which in this case is MyCompany.MyProduct.MyAddin in C#. Because an assembly can contain more than one control add-in, the Microsoft Dynamics NAV Windows client uses the Microsoft.Dynamics.Framework.UI.Extensibility.ControlAddInExportAttribute attribute to differentiate each control add-in that is found in an assembly. The Microsoft.Dynamics.Framework.UI.Extensibility.ControlAddInExportAttribute.Name is used to register the control add-in in Microsoft Dynamics NAV Server. For more information, see How to: Register a Windows Client Control Add-in.

  5. Implement the abstract base method Microsoft.Dynamics.Framework.UI.Extensibility.WinForms.WinFormsControlAddInBase.CreateControl and add code that defines the control add-in.

    C# Copy Code
    protected override Control CreateControl()
           {
               /// Include control add-in code here.
           }
  6. Add code to override additional base class members as required for your control add-in.

    For example, a field control on a Microsoft Dynamics NAV Windows client can have a caption. If you do not want a caption, then override the Microsoft.Dynamics.Framework.UI.Extensibility.WinForms.WinFormsControlAddInBase.AllowCaptionControl property and return false (the default value is true).

    C# Copy Code
    public override bool AllowCaptionControl
    {
    get 
    { 
     return false;
    }

    The caption will span the caption column and the data column of the page.

  7. To bind the control add-in to data in the Microsoft Dynamics NAV database, add the following code that gets or sets the Microsoft.Dynamics.Framework.UI.Extensibility.IValueControlAddInDefinition.Value property.

    C# Copy Code
    /// Gets a value indicating whether the Value property has
    /// changed its value.
    public bool HasValueChanged { get; set; }
    /// Gets or sets the Value Property.
    public object Value
    {
        get
        {
            // Include value handling code here.
            return null;
        }
        set
        {
            // Include value handling code here.
            
        }
    }
    
    Note
    The Microsoft.Dynamics.Framework.UI.Extensibility.WinForms.StringControlAddInBase class already overrides the Microsoft.Dynamics.Framework.UI.Extensibility.IValueControlAddInDefinition.Value property to transfer data between the control add-in and the Microsoft Dynamics NAV database.

    For more information, see Binding a Windows Client Control Add-in to the Database.

  8. To define events that call the OnControlAddin C/AL trigger of a page field control, add the following C# code to declare an event handler.

    C# Copy Code
       public event ControlAddInEventHandler ControlAddIn;

    Add code to raise the event where appropriate.

    For more information, see Exposing Events and Calling Respective C/AL Triggers from a Windows Client Control Add-in.

  9. To add an event that will be represented by a new trigger in C/AL code of a Microsoft Dynamics NAV page object, use the managed attribute ApplicationVisibleAttribute and add code for C# methods and properties.

    C# Copy Code
    [ApplicationVisible]
         public void DrillDown(int nodeId)
         {
          …
         }
         public int SelectedNode
         {
          get {…}
          set {…}
         }    
    

    The methods and properties must be public. For more information, see Exposing Methods and Properties in a Windows Client Control Add-in.

  10. To add a method or property that can be called from the C/AL code of a Microsoft Dynamics NAV page object, use the managed attribute ApplicationVisibleAttribute and add code for C# methods and properties.

    C# Copy Code
    /// <summary>
    /// Event will be fired when the AddIn is ready for communication through its API
    /// </summary>
    [ApplicationVisible]
    public event MethodInvoker AddInReady;
    

    The methods and properties must be public. For more information, see Exposing Methods and Properties in a Windows Client Control Add-in.

  11. Build and sign the solution.

Signing an Assembly That Contains a Control Add-in

To use an assembly that contains a control add-in with the Microsoft Dynamics NAV Windows client, it must be signed. Signing gives the assembly a public token key, which is a unique identity that is used to make sure that the control add-in runs code from a trusted assembly. When you register a control add-in in Microsoft Dynamics NAV Server, you provide the public token key. At run time, the Microsoft Dynamics NAV Windows client uses the public token key to load the appropriate control add-in.

Assemblies are signed with a key file that contains the public key token and an optional password. You can sign an assembly that contains a control add-in by creating a new key file or using an existing one. For more information about how to sign assemblies, see How to: Sign Assemblies and Strong-Name Signing for Managed Applications.

To sign the Microsoft Dynamics NAV Windows client add-in assembly

  1. Open the project's properties.

  2. On the Properties window, choose the Signing tab.

  3. Select the Sign the assembly check box.

  4. In the Choose a strong name key file box, select New to create a new key file or Browse to use an existing key file.

  5. Choose the OK button.

For information about how to determine the public token key, see How to: Determine the Public Key Token of the Windows Client Control Add-in.

Example

The following code illustrates a control add-in that implements the Microsoft digital ink control on a Microsoft Dynamics NAV Windows client page field. For example, you could use this control add-in on a sales order page to allow customers to sign their sales orders with a tablet PC. The control add-in is designed to bind with a table field in the Microsoft Dynamics NAV database to store and retrieve signatures. Because the signatures are transferred as binary data, the example implements the Microsoft.Dynamics.Framework.UI.Extensibility.IObjectControlAddInDefinition interface.

C# Copy Code
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Ink;
using System.Drawing;
using Microsoft.Dynamics.Framework.UI.Extensibility;
using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;
using System.Windows.Forms;
namespace NavInkControl
{
    [ControlAddInExport("MyCompany.MyProduct.MyNavInkControlAddin")]
    public class NavInkContol : WinFormsControlAddInBase, IObjectControlAddInDefinition
    {
        InkPicture _inkControl;
        private bool _loaded = false;
        /// Creates the control for displaying and adding signatures.
        protected override Control CreateControl()
        {
            _inkControl = new InkPicture();
            _inkControl.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            _inkControl.MinimumSize = new Size(40, 50);
            _inkControl.MaximumSize = new Size(Int16.MaxValue, 100);
            return _inkControl;            
        }
        #region IObjectControlAddInDefinition Members
        public event ControlAddInEventHandler ControlAddIn;
        /// Gets a value indicating whether the Value property instance has changed. true if this instance has changed its value; otherwise, false.
        public bool HasValueChanged
        {
            get { return _inkControl.Ink.Dirty; }
        }
        /// Gets or sets the value.
        public object Value
        {
            get
            {
                return this._inkControl.Ink.Save();
            }
            set
            {
                if (value is byte[])
                {
                    byte[] data = (byte[])value;
                /// Specifies that the data loads only once so that data cannot load while the user is drawing.
                    if (data != null && !this._loaded)
                    {
                        this._inkControl.Ink.Load(data);
                        this._loaded = true;
                    }
                }
            }
        }
        #endregion
    }

See Also