Add-Ins for the RoleTailored client of Microsoft Dynamics NAV 2009 SP1 (part1)

(updated: Sample project download: Sept 09) 

(updated to SP1 CTP2 and release API: 07.June09)

Extensibility for the RoleTailored client also called “Add-ins”, is the feature which I personally love most in our SP1 release of Microsoft DynamicsNav 2009. Starting with this service pack partners have the possibility to add custom controls to the IU of the RoleTailored client.

These controls can be anything - from a static logo picture (not read from the database), to an edit control with rich formatting, to a web browser control pointing to sites relevant for the user or his role or to advanced data visualizations. These controls are truly hosted within the pages of the RoleTailored client and treated with the same respect as the build-in controls.

In this post I want to introduce the concept of Add-ins for the RoleTailored client and show the most basic code sample.

(We will have a few minor changes to the Interface when we release, and I will update my posts when it comes out.)

For the restless reader (“in a few words”)

 

GoldenCaller  

Using a control Add-in

  • Control Add-ins are contained in assemblies.
  • Add-in assemblies must be placed in the “Add-ins” directory of the RoleTailored client.
  • Each Add-in must be registered in the C/Side development environment with at least its name and public key token.
  • For any field on a page the property ControlAddIn can be used to specify a custom control.

Creating a simple control Add-In

  • Create a .NET class library
  • Declare a class of a certain base class add apply a certain attribute with a name for your Add-In:
  •  [ControlAddInExport("MyFirstAddIn")]public class MyControlAddIn : WinFormsControlAddInBase
  • Implement the method:

     protected override System.Windows.Forms.Control CreateControl()
Download source code here

 

The concept of Add-ins

Add-ins are contained in a DLL file, which must be a managed assembly. They are discoverable artifacts, which follow certain standards. An Add-in is the provider of a control that can be rendered and hosted in the layout of the UI of the RoleTailored client. Controls from an Add-in can only be used on pages and not on forms for the Classic client.

How to to utilize existing Add-Ins

The C/Side development environment must be made aware of an Add-In. All Add-Ins must be registered in Table 2000000069 (“Client Add-In”). The required information, such as the Control Add-in Name and Public Key Token, are typically delivered by the provider of an Add-in.

ClientAddInTable

In an upcoming blog post I will make a tool available that allows you to select one or more assemblies and register all contained Add-ins.

The property ControlAddIn of a field on a page must set in order to select a certain Control Add-in.

DevTool

Control Add-ins are supported for stand alone fields on a page. Please note the exception: Fields in a repeater are not supported yet.

How to write an Add-in

For the Add-in developer: What essentially is an Add-in?

  • An Add-in is essentially composed by an interface which tells the RoleTailored client how it should communicate with the client. And a class which implements the interface. Both the interface and the class declaration must be equipped with certain attributes by which they will be discovered in an assembly.
  • The assembly, which is a compiled Add-in library, must be placed in the “Add-ins” subdirectory of the program directory of the RoleTailored client (something like: c:\Program Files\Microsoft Dynamics NAV\60\RoleTailored client\Add-Ins). Also referenced assemblies might need to be copied there.
  • The Add-in class works as a factory. It will instantiate a WinForms control and deliver an instance to the RoleTailored client. The control can really be any you can think off: a standard WinForms control , a 3rd party control, or a control you have developed yourself.
  • The Add-in class will provide the plumbing between the control and the RoleTailored client. This includes routing back and forth of a value to show or edit, setting sizing and other layout options and firing a trigger in C/AL code. The Add-in class has access to a set of tools which allow it to further interact with the environment it is running in.

But don’t worry, so much about all the options right now. In this post i will begin with a basic sample and you will see how simple it really is to create an utilize an Add-In.

So, which tools do I need to create an Add-in?

  • Any version of Microsoft Visual Studio 2005/2008 is good. For example Visual Studio Express for C# (which is a free download)
  • The library Microsoft.Dynamics.Framework.UI.Extensibility.dll. You will typically find the library in the program directory of the RoleTailored client (something like: c:\Program Files\Microsoft Dynamics NAV\60\RoleTailored client).

 

The first Add-in Sample

1. Create a project for an Add-in

My first Add-in sample is a simple static picture control. The special characteristic is that picture data has been embedded into the control instead of having to retrieve it through data binding from a table on the server. This could be used for a static Logo. Instead of embedding the data into the picture, the control could load pictures from a local store or a Web Service instead – but this out of scope of my goal for this blog post.

I start by creating a class library in Visual Studio. In Solution Explorer add a reference to the library above. Then, in the Project settings I create a new signature file. If I had created Add-ins before, I might choose to use the same signature for all and select an existing signature file from another project.

image

Idea

Please note: It is required that Add-in libraries are strong signed. This requires that all referenced libraries are also strong signed. This is not an issue for any of the .NET Framework libraries. But you might find 3rd party libraries that have not been signed. You can sign those yourself with the signing tool of the .NET Framework.

2. Add a code unit for the interface and implementing class of an Add-in

Now I add one code unit to the project. In it I declare a public class with the [ControlAddInExport("name")] Attribute. The chosen namespace and the name of the class do not matter as far as how the Add-in is exposed. However, is the name you have chosen is essential for theControlAddInExport attribute. This name together with the Public Key Token of the assembly signature will be used at runtime to identify the Control Add-in.

 using System.Windows.Forms;
using Microsoft.Dynamics.Framework.UI.Extensibility;
using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

namespace AddInSamples
{


    [ControlAddInExport("SampleControl1_StaticPicture")]
    public class MyStaticPictureControlAddIn : WinFormsControlAddInBase
    {     
    }
}

The class is derived from one of the Control Add-in base classes for the WinForms Display Target – which represents the RoleTailored client. These base classes can all be found in the namespace: Microsoft.Dynamics.Framework.UI.Extensibility.WinForms
Because my picture control Add-in does not show any data from the backend server and does not communicate with it, I have chosen the base class WinFormsControlAddInBase, which has no pre-built support for any of these behaviors.

 

In follow-up posts we will see how other base classes and interface can be used to declare the way an Add-in communicates with the RoleTailored client. Interfaces will play a much stronger role when it comes to Add-ins for multiple display targets and custom methods, properties and events – in future releases.

3. Implement the Add-in interface

 

 

Next I need to provide an implementation for the abstract method CreateControl. This is the place where I instantiate a PictureBox control and load it with an image, that I had added to a resource file in the project.

 [ControlAddInExport("SampleControl1_StaticPicture")]
public class MyStaticPictureControlAddIn : WinFormsControlAddInBase
{

    protected override System.Windows.Forms.Control CreateControl()
    {


        PictureBox pic = new PictureBox();
        pic.Image = StaticPictureResources.Logo;
        return pic;
    }

}

After compilation of my project I already have a fully functional Add-in. But we still need to fine-tune it a bit until it looks good:

 image

4. Add special sizing and preventing the field title

Two modifications should be applied:

  1. This control should never have a field title
  2. This control should always be sized to the picture content

Modification 1 is achieved by overriding the virtual property AllowCaptionControl

 public override bool AllowCaptionControl
{ get { return false; } }

Modification 2 is done by setting the MinimumSize and MaximumSize of the PictureBox control.

 protected override System.Windows.Forms.Control CreateControl()
{
    PictureBox pic = new PictureBox();
    pic.Image = StaticPictureResources.World;
    pic.MinimumSize = pic.MaximumSize = pic.Image.Size;
    return pic;
}

Perfect ! Now we have a static picture, by default without a title and sized to the original size of the embedded picture.

image

Idea You should take the tutorial in this blog as a sample of non-data bound content from any source on a page in the RoleTailored client of Microsoft Dynamics NAV 2009.

My next blog post will show how to create a custom text box, bound to data.

 

 

Stay tuned!

Christian Abeln
Senior Program Manager
Microsoft Dynamics NAV

Comments

  • Anonymous
    July 06, 2009
    Hi Christian, I tried your example but when i run the page i get the following error: The page contains a control add-in that is not permitted. Contact your system administrator. Double checked the public key, replaced the picturebox with a panel control. Still same message. Any ideas please? By the way, i used our companies license that was updated for nav 2009, perhaps i need a update for sp1? Thanks in advance for your time.

  • Anonymous
    September 02, 2009
    This situation appears typically when the Add-in has not been registered in the "Client Add-Ins" table in the database. You can enter the information manually or use my Registration Tool.(http://blogs.msdn.com/cabeln/archive/2009/06/08/registration-tool-for-dynamics-nav-roletailored-client-add-ins.aspx)

  • Anonymous
    December 04, 2009
    This post is very helpful for beginners.I am getting the following error when I run the page which has field with ControAddin property. Please suggest me the solution. Could not locate the add-in library for 'AddinSample2;PublicKeyToken=b67ed1865dcb7ad4'.

  • Anonymous
    December 04, 2009
    The message like "Could not locate the add-in library for 'AddInSample2;PublicKeyToken=...' appears in the UI of the RoleTailored client for the field where the ConrolAddIn has been set but:an Add-In class with the specified Name ('AddInSample2' in this sample) set as an Attribute [ControlAddInExport("AddInSample2")]could not be found on a public class in one of the libraries in the "Add-Ins" directory of the "RoleTailored Client" in Program Files (or any subdirectory of that), where the library has also been strong name signed with a keypair of which the public key is the same as in "PublicKeyToken".

  • Anonymous
    December 06, 2009
    Hi ChrisAbeln, I understand the mistake I did. I should have used the name specified in the [ControlAddInExport("AddInSample2")]. It worked. Thanks...

  • Anonymous
    February 01, 2010
    Nice blog! Keep it going! Greetings

  • Anonymous
    August 02, 2010
    It's a nice place for beginners to NAV 2009. Thank You!

  • Anonymous
    January 02, 2011
    Hi Chris,i've found your post very usefull, but I've an issue with my add-in height.In my case I've used a webbrowser object and I would like to fit it to the 100% of the Nav window, but at the moment I'm only able to specify a fixed height.Do you have any suggestion about? I have tried also with the wb.parent height, but without successMany thanksAdrianoHere is my code:          wb = new WebBrowser();           Size wbh= new Size();          wbh.Height=650;           wb.MinimumSize = wbh;           return wb;

  • Anonymous
    January 02, 2011
    Hi Adrino,you should use the property MaximunSize and MinimumSize. Setting the Size property has no impact, because the layout engine will take control over the Size.this.myWebBrowser = new WebBrowser{    Dock = DockStyle.Fill,    MaximumSize = new System.Drawing.Size(int.MaxValue, int.MaxValue),    MinimumSize = new System.Drawing.Size(600, 400) // in case you would want a minimum size};If you then utilize a PageType (like List, ListPlus, ListPart) that is designed for a filling control, you can have a page / part filling WebBrowser control easily.Good luck!Christian Abeln

  • Anonymous
    February 24, 2014
    I want to show the customer table in AddIn ? Can anyone let me know how to do this?