Using Client Extensibility in NAV 2009 SP1 to create Charts

Using Client Extensibility in NAV 2009 SP1 to create Charts

  • Comments 7

 

Just to get a bit of practice with Client Extensibility, I experimented with some examples I got. They use MS chart controls to build chart

components for RTC. As it turned out, the result was something that might even be useful as well. So this post has these two

purposes: 1)  Some relatively simple examples of Client Extensibility, and 2)  hopefully in the process to make something that can

actually be useful.

 

Of course - as always - the information in this post is un-supported and no responsibility is assumed. In particular when working with

Client Extensibility add-ons, one has to be careful of handling any potential error in the add-on. If the add-on meets an unhandled exception,

then RTC may crash. So if you decide to extend the example here (and I hope you do), then just be careful to trap as many potential

exceptions as possible in your Visual Studio code. This is lesson one for creating Client Extensibility Add-ins...

 

However I would encourage any feedback - just post it here at the end of this post. Is this useful, what else would be useful, etc. Both

for learning this new technology, and I would also welcome any ideas for charts that might be useful.

 

Also check these links for much more information on Client Extensibility:
  Christian's blog
  Extending the RoleTailored Client Using Control Add-ins in Microsoft Dynamics 2009 SP1

 

New blogs on this topics may follow - all depending on the response to this one. For now, this post shows how to achieve two different types of charts, looking like this:

 

 

CustPage

  

Making charts with Clients Extensibility for NAV 2009 SP1 using the "Microsoft Chart Controls add-on for MS Visual Studio"

First, you need to download and install these two components:

Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008

Microsoft Chart Controls for Microsoft .NET Framework 3.5

 

Then from here you can take the easy way and just use the completed project that I attached at the end of this post. Or the hard way, and follow the full directions below. First, if you just want to see what this is, here is how to implement this example from the files attached here:

 

Implement the Client Add-in control:

As the name suggests, Client Extensibility add-ons run on the client (RTC). In NAV 2009 SP 1, the RTC folder contains a new subfolder called "Add-ins" (default C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client\Add-ins). So unzip the attached file "XTCharts.zip", then copy the files from "XTCharts\bin\Debug\" into the Add-ins subfolder in RTC.

Next, open a Classic Client and "Register" this add-in for the client: Run table 2000000069 "Client Add-in", and enter a new line:


Control Add-in Name:    XTChart
Public Key Token:    d1a25808afd603da

It's important that you call it exactly this, since both the Add-in Name and the Public Key Token refer to these specific dlls (explained further below).

This example includes codeunit 75550 "XT Chart Util" which has functionality generating the data that the charts are based on. So import XTChart.fob.

Finally, add a chart control to a page. For this example add it to page 21 "Customer Card": In Page Designer, first create a new global variable called XTChartUtil, Type = Codeunit, SubType = XT Chart Util. To add the line-chart:

add a new line called "Sales (LCY)" of type "Field", and specify these two properties:

SourceExpr = XTChartUtil.CustPointsChart(Rec)

ControlAddIn = XTChart;PublicKeyToken=d1a25808afd603da

And to add the pie-chart, add a new line with these proerties:

SourceExpr = XTChartUtil.CustDoughnutChart(Rec)

ControlAddIn = XTChart;PublicKeyToken=d1a25808afd603da

Save and compile the page, then start RTC, and the Customer Card page should now look as in the picture above.

 

What this example gives, is: 1) A chart showing "Sales (LCY)" for the last 6 months, and a doughnut chart that shows the percentage of Balance compared to Credit Limit.

Designing the client Add-in control:

Hopefully by following the steps above, you should now have charts on your Customer Card. So here is how you would have designed it from scratch instead of using the attached example.

To get started, open up Visual Studio 2008. Create a new project of type Class Library. In the project that opens, in the Solution Explorer, right click References, and select "Add Reference...". Here we need to add a few references:

From the "Browse" tab, browse to the folder where you have Dynamics NAV RoleTailored Client installed (default C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client), and select Microsoft.Dynamics.Framework.UI.Extensibility.dll. This is the library that is always needed when making a Client Extensibility add-on.

Add another reference, this time from the ".NET" tab select System.Windows.Forms.DataVisualization. This is the library that you installed from the links above. And, finally, also from the ".NET" tab, add System.Windows.Forms

Also add references to these in code, like this in the top:

using System.Windows.Forms.DataVisualization.Charting;

using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

using Microsoft.Dynamics.Framework.UI.Extensibility;

using System.Windows.Forms;


 

And now you are ready to start using functionality from Client Extensibility, and from Microsoft Chart Controls.

To start any Client Add-in control, you need two things:

[ControlAddInExport()]-declaration just before the class you make, and

protected override Control CreateControl() which is the function that RTC runs when initialising a Client Extensibility Add-in. Your project should now look like this:

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms.DataVisualization.Charting;

using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

using Microsoft.Dynamics.Framework.UI.Extensibility;

using System.Windows.Forms;

namespace ClassLibrary8

{

[ControlAddInExport("XTChart")]

public class XTChartClass : StringControlAddInBase

{

protected override Control CreateControl()

{

Chart XChart = new Chart();

return (XChart);

}

}

}

 

You must remember the name you decide on, in this line:

 [ControlAddInExport("XTChart")

This is the name (XTChart) that must match the entry in table 2000000069 "Client Add-in".

This is the minimum code needed - you can of course now also specify a number of properties for your chart control, like colours, chart types, etc. As long as you create your control here, and then return it back to RTC.

The next question is: how do we send data from RTC to our control? This done by adding these lines:

public override string Value

{

get

{

return base.Value;

}

set

{

base.Value = value;

}

}

 

This is the Value that you get from RTC. RTC sends it via the SourceExpression of the Control Add-in when you add it to a page. When you add an Add-in to a page you don't have to specify SourceExpression, but if you want to send data from RTC to the Add-in, then this is how to do it. In this example there is a codeunit to generate chart-data, but SourceExpression can also just be a field.

In the section you just created, you can now refer to the chart like this: 

((Chart)this.Control)

So when receiving data from RTC, you can then set ChartType, Data, and any other properties on the chart.

 

You must also sign the project: In Project Properties, on the "Signing"-tab, you must tick "Sign the assembly". This embeds a public key token in the .dll when you build it, and this is the token (here d1a25808afd603da) that must also be entered into table 2000000069. Visual Studio does not tell you what the token is, so to obtain it, after building your project open a Visual Studio Command Prompt, and run "sn -T XTCharts.dll" to find out what the public key token is for XTCharts.dll.

 

In this example, we send an XML structure to the Add-in, which is generated by the codeunit. The structure is like this:

- <Chart>
    <ChartType>2</ChartType>
- <Data>
    <Aug>446.04</Aug>
    <Sep>334.53</Sep>
    <Oct>0</Oct>
    <Nov>111.51</Nov>
    <Dec>501.8</Dec>
    <Jan>1,499.02</Jan>
<</Data>
 </Chart>
 
 So basically, we have one node for the Chart Type (1 is for a point-chart, and 2 is for a doughnu chart). And then there is a data-section for the Series in the chart.
 
Finally, in the code below, also notice these lines:

try { - do code..}

catch{MessageBox.Show("An error occurred ");}

 
I am not a c# developer, so this way of doing error handling is likely not optimal. But if any kind of error happens in the code, and it is not inside of a try{}-structure, then the Add-in may crash, and when that happens, RTC will also crash. In this example, instead of a crash, we would get a message and RTc would stay open.
 
 
So, below is the whole code from the attached example. Remember this particular code is designed specifically receive data in a specific format, done by the attached codeunit. So it can of course be simplified, or of course even more so, it is something that can be improved on.
 
 
 
Again, I hope this is useful for getting insight into Client Extensibility, but also maybe it can be used as a basis for making some useful components - comments are more than welcome,
 
Best regards
Lars
 
 
 
 
 
 
Full code:
 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms.DataVisualization.Charting;

using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

using Microsoft.Dynamics.Framework.UI.Extensibility;

using System.Windows.Forms;

using System.Drawing;

using System.Xml;

namespace XTCharts

{

[ControlAddInExport("XTChart")]

public class XTChartClass : StringControlAddInBase

{

protected override Control CreateControl()

{

Chart XChart = new Chart();

XChart.Series.Add("Series1");

XChart.ChartAreas.Add("Default");

XChart.Width = 100;

XChart.Height = 100;

return (XChart);

}

public override string Value

{

get

{

return base.Value;

}

set

{

try

{

if (Convert.ToString(value) != "")

{

((Chart)this.Control).Series["Series1"].Points.Clear();

String TempXML = value;

XmlDocument XMLDoc = new XmlDocument();

XMLDoc.LoadXml(TempXML);

// Chart Type

XmlNode Node = XMLDoc.SelectSingleNode("Chart/ChartType");

switch (Convert.ToString(Node.InnerText))

{

case "1":

((Chart)this.Control).Series["Series1"].ChartType = SeriesChartType.Spline;

((Chart)this.Control).BackColor = Color.AliceBlue;

break;

case "2":

((Chart)this.Control).Series["Series1"].ChartType = SeriesChartType.Doughnut;

break;

default:

MessageBox.Show("Invalid ChartType " + Convert.ToString(Node.InnerText));

break;

}

// Chart Data

XmlNodeList Nodes = XMLDoc.SelectNodes("Chart/Data/*");

for (int i = 0; i < Nodes.Count ; i++) {

Node = Nodes.Item(i);

((Chart)this.Control).Series["Series1"].Points.AddXY(Node.Name, Convert.ToDouble( Node.InnerText));

}

}

}

catch{MessageBox.Show("Error with data from NAV " + value);}

}

}

 

 

}

}

 
 
Attachment: XTCharts.zip
Leave a Comment
  • Please add 1 and 5 and type the answer here:
  • Post
  • Hi,

    What is subtype of the automation vars that you use in CU 75550.

    Br

    Kenneth

  • The Automation vars are all for XML. I use Version 4, like here for example:

    'Microsoft XML, v4.0'.DOMDocument

    It would be safe enought to use Version 6 if you don't have Version 4. I hope this helps?

  • Hi Lars,  

    Could this be easily modified to allow to Series.  For example allowing sales and profit to show on the same Chart ?

    Stephen

  • Hi Stephen,

    It can indeed do multiple series - check the next blog in this series:

    blogs.msdn.com/.../more-charts.aspx

    There is still the limitation that the whole chart definition can maximum be 1024 characters. Something which you may hit if you start adding more series. I hope to address that one day, if the interest for these charts is big enough.

    Thanks for your interest!

  • The following must be installed on the server or client system.

    Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008

    Microsoft Chart Controls for Microsoft .NET Framework 3.5

  • The codeunit cannot be compiled.

    Sub Type of Automation 'Microsoft XML, v4.0'.DOMDocument does not exists in my pc. Instead I get 'Microsoft XML, v4.0'.Unknown Class'.

  • The codeunit uses XML V4, so likely you just need to change that to XML V6. In variables, just change:

    'Microsoft XML, v4.0'.DOMDocument

    'Microsoft XML, v4.0'.IXMLDOMNode

    to

    'Microsoft XML, v6.0'.DOMDocument

    'Microsoft XML, v6.0'.IXMLDOMNode

    And see if that compiles?

Page 1 of 1 (7 items)