Blog Archives

CRM 4 Silverlight Integration

In this post I will talk about integrating the Microsoft Dynamics CRM UI with Silverlight and I will show how to inject a Silverlight control onto a CRM entity form.

Normally one would extend CRM by using javascript or custom dialogs but Silverlight is a new technology that allows the building of a nice UI that can interagate well with the underlying html page and backend systems.

The solution consists of a custom web application that hosts the silverlight required files and some customisations for the “OnLoad” event. On this occasion I will show you how to show a modal Silverlight popup on the opening of a new CRM form, however the concepts in this post can be easily extended to cater for other requirements. Below is a screen shot of the final result. You can then click anywhere on the popup to dismiss it.

CRM_Silverlight_Popup

We start with creating some methods that will inject a silverlight control onto a CRM form. To be able to create a modal popup I will create an overlay div that will cover the whole window preventing the user from interacting with anything on the form until the popup is dismissed. To display the Silverlight control I will place another silvelright container div on top of the overlay div that will contain the Silverlight control. The Silverlight container div will be the exact size of the Silverlight popup control and will be centered in the middle of the window. Both divs will be appened to the end of the document and use absolute layout to prevent any intervention with the CRM elements on the form.

The next step is to inject the Silverlight control into the Silverlight container div using the standard method that comes as part of the Silverlight.js file. Finally the overlay div and container div are shown on the form. Below is the code that illustrates this.

   13 if (!window.SilverlightInjector)

   14 {

   15     window.SilverlightInjector = {};

   16 }

   17

   18 SilverlightInjector.CreateModalSilverlightControl = function(controlSource, id, params, width, height, onLoadHandler) {

   19

   20     var screenOverlay = document.getElementById(‘screenOverlay’);

   21     var silverlightContainer = document.getElementById(id + ‘_silverlightContainer’);

   22

   23     if (“undefined” == typeof (screenOverlay)

   24         || “unknown” == typeof (screenOverlay)

   25         || null == screenOverlay) {

   26         screenOverlay = document.createElement(‘div’);

   27         screenOverlay.style.width = ‘0px’;

   28         screenOverlay.style.height = ‘0px’;

   29         screenOverlay.style.top = ‘0’;

   30         screenOverlay.style.left = ‘0’;

   31         screenOverlay.style.position = ‘absolute’;

   32         screenOverlay.style.zIndex = ‘100’;

   33         screenOverlay.id = ‘screenOverlay’;

   34         screenOverlay.style.display = ‘none’;

   35         screenOverlay.style.background = ‘#000000’;

   36         screenOverlay.style.filter = ‘alpha(opacity=25)’;

   37

   38         document.body.appendChild(screenOverlay);

   39     }

   40

   41     if (“undefined” == typeof (silverlightContainer)

   42         || “unknown” == typeof (silverlightContainer)

   43         || null == silverlightContainer) {

   44         silverlightContainer = document.createElement(‘div’);

   45         silverlightContainer.id = id + ‘_silverlightContainer’;

   46         silverlightContainer.style.position = ‘absolute’;

   47         silverlightContainer.style.zIndex = ‘101’;

   48         silverlightContainer.style.width = width;

   49         silverlightContainer.style.height = height;

   50         silverlightContainer.style.display = ‘none’;

   51

   52         document.body.appendChild(silverlightContainer);

   53     }

   54

   55     //set overlay size to window full size

   56     screenOverlay.style.width = document.body.clientWidth;

   57     screenOverlay.style.height = document.body.clientHeight;

   58

   59     //place container in the center of the window

   60     silverlightContainer.style.top = (document.body.clientHeight – height) / 2;

   61     silverlightContainer.style.left = (document.body.clientWidth – width) / 2;

   62

   63     Silverlight.createObject(

   64         controlSource,                  // Source property value.

   65         silverlightContainer,                  // DOM reference to hosting DIV tag.

   66         silverlightContainer.id + “_silverlightPlugin”,         // Unique plug-in ID value.

   67         {                               // Per-instance properties.

   68         width: ‘100%’,                // Width of rectangular region of

   69         // plug-in area in pixels.

   70         height: ‘100%’,               // Height of rectangular region of

   71         // plug-in area in pixels.

   72         inplaceInstallPrompt: false, // Determines whether to display

   73         // in-place install prompt if

   74         // invalid version detected.

   75         background: ‘transparent’,       // Background color of plug-in.

   76         isWindowless: ‘true’,       // Determines whether to display plug-in

   77         // in Windowless mode.

   78         framerate: ’24’,             // MaxFrameRate property value.

   79         version: ‘2.0’               // Silverlight version to use.

   80     },

   81         {

   82             onError: SilverlightInjector.OnErrorSilverlightEventHandler,               // OnError property value —

   83             // event handler function name.

   84             onLoad: onLoadHandler                // OnLoad property value —

   85             // event handler function name.

   86         },

   87         params                      // initParams

   88         );

   89

   90     //show the Silverlight container lock the screen

   91     silverlightContainer.style.display = ‘block’;

   92     screenOverlay.style.display = ‘block’;

   93 }

The next step is to create some code that will be injected into the CRM entity “OnLoad” event. I prefer placing any code that is used on the “OnLoad” event in a separate file on the server as it can be easily maintained, especially during development. However be aware that in this case these extra customisations are not stored in the database and will have to be deployed separately.

The first thing to do is to inject the standard Silverlight.js into the head of the page as a script element. I found that loading the file normally will not auto activate the silverlight control and the user will have to click on it to activate it. The next thing is to load SilverlightInjector.js file created in the first step into the form in a smilar fashion and call the method to create the Silverlight popup. The code below illustrates this step.

   13 if (!window.EntityOnLoad)

   14 {

   15     window.EntityOnLoad = {};

   16 }

   17

   18 EntityOnLoad.Load = function() {

   19     //Load Silverlight.js into the head to prevent having to activate the control

   20

   21     var oXML = new XMLHttpRequest();

   22     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/Silverlight.js’, false);

   23     oXML.send();

   24

   25     var e = document.createElement(“script”);

   26     e.type = “text/javascript”;

   27     e.text = oXML.responseText;

   28     document.getElementsByTagName(“head”)[0].appendChild(e);

   29

   30

   31     //Load SilverlightInjector.js

   32

   33     oXML = new XMLHttpRequest();

   34     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/SilverlightInjector.js’, false);

   35     oXML.send();

   36     eval(oXML.responseText);

   37

   38     EntityOnLoad.ShowPopupMessage(‘This is a ‘ + crmForm.ObjectTypeName + ‘ form displayed using Microsoft Silverlight.’, 300, 300);

   39 }

   40

   41 EntityOnLoad.ShowPopupMessage = function(message, width, height) {

   42     var params = ‘message=’ + message;

   43     params += ‘,width=’ + width;

   44     params += ‘,height=’ + height;

   45     SilverlightInjector.CreateModalSilverlightControl(‘/ISV/CRMSilverlightWeb/ClientBin/CRMSilverlightLibrary.xap’, ‘CRMPopupID’, params, width, height, null);

   46 }

We now need to use this code from the CRM form on the “OnLoad” event. To do this we the load the code using the standard XmlHttpRequest and invoke the load function we created previously. The code below needs to be placed into the customisations on the “OnLoad” event for the entity you want to use the popup on.

    1 try {

    2     oXML = new XMLHttpRequest();

    3     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/EntityOnLoad.js’, false);

    4     oXML.send();

    5     eval(oXML.responseText);

    6

    7     EntityOnLoad.Load();

    8 }

    9 catch (ex) {

   10     alert(‘Failed to load :’ + ex.description);

   11     window.close();

   12 }

The last call we made will download and launch the Silverlight application. On Application start event we create a new CRMPopup control and pass the initialisation parameters to the constructor. The CRMPopup is a Silverlight user control that implements the Popup behaviour. The control is initialised by passing a message and dimensions through the initialisation paramters. In the constructor we register for two events: The Loaded event that will start the animation to show the control and the MouseLeftButtonUp event that will be used to start an animation to hide the control.  We will not go too much into the details of the Silverlight animations as it is outside the scope of this post.

I have included some sample code that you can download using the link below. The download contains a solution with a web application project and a Silverlight control library. You will need to create a virutal directory called “CRMSilverlightWeb” under the ISV directory in CRM and copy the content of the web application into there. Make sure to add the “.xap” extension to the MIME types on the “ClientBin” directory otherwise IIS will not allow access to the Silverlight package.  You can set the extension to “.xap” and MIME type to “application/x-silverlight-2”.  You will also need to add the contents of “EntityOnLoadCustomisation.js” file to “OnLoad” event of the selected entity you want to test the popup on.

You might notice a small delay the first time you load the page and this is due to the form having to download the Silverlight package. On subsequent requests and (depending on your setup) the Siverlight package can be cached to increase performance.

In this post we have seen how to show a model popup on a crm form using Silverlight. I would just like to mention that this concept can be used to implement other types of functionality (including things like address checking where you could have a control that reads your search criteria and provides a list of matches and then save back the details onto the CRM form).  Essentially it could be used for any process that requires some user interaction as an alternative to javascript and dialogs. By using Silvelright you get the extra benefit of having a nice user interface that is easy to implement and has the advatange of using a proper programming language such as C#.

You can download the sample code from here.