Register  Login
Silverlight 1.0 » Start Here
Silverlight Module (live sample)
 Print   

Creating a DotNetNuke Silverlight Module For Absolute Beginners

Why DotNetNuke and Silverlight?

Silverlight is an application that runs in the web browser. It has it's own operating system and one would be tempted to create solutions completely using Silverlight. For example, let's assume you wanted to create a Photo Gallery. Soon you would realize that you need a method to allow an administer to upload pictures to the gallery. Also, you need to implement security to only allow the administrator to upload pictures. You would also want to give the administrator the ability to create multiple picture albums.

Implementing this functionality will usually consume more time and resources than the Silverlight Photo Gallery itself.  The logical solution is to leverage the free open source DotNetNuke Portal Framework and create a DotNetNuke Silverlight module, because DotNetNuke has an extensive user and roles management system. This will allow you to concentrate on the primary functionally of your Silverlight application.

Challenges with DotNetNuke Silverlight modules

Silverlight 1.0 applications are primarily comprised of XAML files and JavaScript. DotNetNuke allows for a single module to be placed on a page multiple times. This can cause undesired behavior as Silverlight requires a uniquely named DIV for each Silverlight control on the page that must be initialized by JavaScript. The JavaScript would not know the name of this DIV tag because it is created at run time. The solution to this is to dynamically create the code that injects the Silverlight module on the page.

Creating a Silverlight module

To best explain how to create a DotNetNuke Silverlight module, it is helpful to first create a normal Silverlight application. To start, we will open Microsoft Expression Blend 2 (or higher). From the File menu, select New Project...

.

From the Create New Project menu, select Silverlight Application (JavaScript), enter a name and click OK.

From the toolbox select the TextBlock control.

Hold down the mouse button as you draw a rectangle. Enter "Click Here" in the box.

Next, select Rectangle from the tool bar.

Hold the mouse button down as you draw a rectangle over the Click Here box.

On the Objects and Timeline box, click the [Rectangle] bar.

While holding the mouse button down, drag it so that it is above the [TextBlock] "Click Here" bar.

This will cause Click Here to now be visible.

Next, hold down the Ctrl key as you click on both the [Rectangle] bar and the [TextBlock] "Click Here" bar so that they are both selected. Right-click on one of them and select Group Into and then Canvas.

Right-click on the [Canvas] bar and select Rename.

Name the bar ClickHere (with no space) and click away.

Now, create a TextBlock "off stage" in the grey area. Enter "Hello World!" in the box.

You will now create an animation for the Hello World! box. Click the ">" arrow on the Objects and Timeline box.

Click the "+" button on the Storyboard box.

In the Create Storyboard box enter Timeline1 for the name, check Create as a Resource and click OK.

Timeline recording is on will show.

On the time line grid, drag the yellow selector and move it to "0:00.300".

Click once on the Direct Selection tool.

Click on the Hello World! box and drag it underneath the Click Here box.

A white block will now appear on the time line grid to indicate a key frame.

Now drag the yellow section bar to "0:00:500". Then, click once on the Selection tool.

Click once on the Hello World! box, release the mouse button and move the mouse to the lower right-hand corner of the box until you see the rotation symbols. Hold down the mouse button and rotate the Hello World! box 90 degrees.

Drag the yellow section bar to "0:00:700" and rotate the Hello World! box another 180 degrees. Now. drag the yellow section bar to "0:01:000" and rotate the Hello World! box another 90 degrees returning it to the following position:

You can click on the the Objects and Timeline Play button to preview the animation.

Now, click the "X" button on the Objects and Timeline box to turn off the storyboard recording.

Click the Project tab to display the project files.

Click the arrow next to Page.xaml to display Page.xaml.js. Double-click on Page.xaml.js to open it.

Replace all the code with the following code, then save the file and close it.

if (!window.SilverlightModule)
window.SilverlightModule = {};

SilverlightModule.Page = function()
{
}

SilverlightModule.Page.prototype =
{
handleLoad: function(control, userContext, rootElement)
{
this.button = rootElement.findName("ClickHere");
this.button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.handleMouseDown));
},

handleMouseDown: function(sender, eventArgs)
{
var mouseDownAnimation = sender.findName("Timeline1");
mouseDownAnimation.begin();
}
}

Return to Microsoft Expression Blend and click the F5 key to run the project. When you click on the Click Here box, Hello World! will animate into view.

You can download the code from here:

SilverlightModule.zip

The Silverlight application explained

This simple application consists of 5 files.

Default.html - This is the entry point for the application. This file contains the following code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SilverlightModule</title>

<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="Default_html.js"></script>
<script type="text/javascript" src="Page.xaml.js"></script>
<style type="text/css">
.silverlightHost {
height: 480px;
width: 640px;
}
</style>
</head>

<body>
<div id="SilverlightControlHost" class="silverlightHost">
<script type="text/javascript">
createSilverlight();
</script>
</div>
</body>
</html>

This contains references to the .js (JavaScript) files that are used by the application. The createSilverlight() line calls a function in the Default_html.js file.

Default_html.js - This file contains the createSilverlight() JavaScript method:

function createSilverlight()
{
var scene = new SilverlightModule.Page();
Silverlight.createObjectEx({
source: "Page.xaml",
parentElement: document.getElementById("SilverlightControlHost"),
id: "SilverlightControl",
properties: {
width: "100%",
height: "100%",
version: "1.0"
},
events: {
onLoad: Silverlight.createDelegate(scene, scene.handleLoad)
}
});
}


if (!window.Silverlight)
window.Silverlight = {};

Silverlight.createDelegate = function(instance, method) {
return function() {
return method.apply(instance, arguments);
}
}

This method is responsible for calling the Silverlight.createObjectEx method (that is contained in the Silverlight.js file). This Silverlight.createObjectEx method is responsible for determining what web browser is being used and loading the proper Silverlight plug-in (an ActiveX plug-in for Internet Explorer and other plug-ins for other web browsers).

The parameters passed to the Silverlight.createObjectEx method associate a JavaScript class (SilverlightModule in Page.xaml.js) and indicate the .xaml file that is to be loaded (Page.xaml). The onLoad parameter specifies a delegate to a method (handleLoad that is in the SilverlightModule class) that will be called when the Silverlight control is instantiated..

Page.xaml - This .xml file contains the markup that represents the objects used in the application. The contents of this file were created using Microsoft Expression Blend (earlier in this tutorial).

Page.xaml.js - This file contains the JavaScript class and methods that respond to the events and manipulate the objects in the Page.xaml file.

if (!window.SilverlightModule)
window.SilverlightModule = {};

SilverlightModule.Page = function()
{
}

SilverlightModule.Page.prototype =
{
handleLoad: function(control, userContext, rootElement)
{
this.button = rootElement.findName("ClickHere");
this.button.addEventListener("MouseLeftButtonDown", Silverlight.createDelegate(this, this.handleMouseDown));
},

handleMouseDown: function(sender, eventArgs)
{
var mouseDownAnimation = sender.findName("Timeline1");
mouseDownAnimation.begin();
}
}

Silerlight.js - This file is provided by Microsoft to control the Silverlight functionality.

The challenges of the DotNetNuke Silverlight module

The primary challenge you will face when creating a DotNetNuke Silverlight module is that the Silverlight.createObjectEx method contains a parameter (parentElement) that indicates the DIV tag in the .html page that the Silverlight plug-in will be injected into. This DIV must have a unique name. A DotNetNuke module can have multiple instances placed on the page at the same time. Therefore, you can use a ASP.NET Panel control that will create a unique DIV at run-time. However, it is impossible to know in advance what the name of the DIV tag will be.

The solution is to dynamically generate the parameters that are passed to the Silverlight.createObjectEx method.

Create the DotNetNuke module

First, install the latest version of DotNetNuke from DotNetNuke.com (see this page for assistance).

From the menu bar select File then Open Web Site... to open the site in Visual Studio (or Visual Web Developer Express). In the Solution Explorer, right-click on the DesktopModules folder and select New Folder.

Name the folder "SilverlightModule"

Right-click on the folder and select Add Existing Item...

Navigate to the Expression Blend project created earlier in the tutorial

Hold down the Ctrl key as you select Page.xaml, Page.xaml.js, and Silverlight.js. Click the Add button. The files will then be imported.

Next, right-click on the SilverlightModule folder and select Add New Item...

Select Web User Control, enter View.ascx for the name, select Visual C# for the language, ensure that Place code in a separate file is checked, and click the Add button.

In the Solution Explorer, double-click on the View.ascx file so that it opens in the editing screen.

Switch to Source view (if it is not already in source view) and replace all the code with the following code and save the page:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="View.ascx.cs" Inherits="DotNetNuke.Modules.SilverlightModule.View" %>
<asp:Panel ID="SilverlightControlHost" runat="server" Height="400px" Width="400px">

<script type="text/javascript">
<asp:Literal ID="lrlSilverlight" runat="server"></asp:Literal>
</script>

</asp:Panel>

Now, right-click on View.ascx in the Solution Explorer and select View Code. The View.ascx.cs file will open in the Editing window. Replace all the code with the following code:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Web.UI.WebControls;
using DotNetNuke;
using DotNetNuke.Common;
using DotNetNuke.Security;
using DotNetNuke.Security.Roles;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Services.Exceptions;

namespace DotNetNuke.Modules.SilverlightModule
{
public partial class View : PortalModuleBase
{

protected void Page_Load(object sender, EventArgs e)
{
try
{
// Silverlight scripts
Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "Silverlight", (this.TemplateSourceDirectory + "/Silverlight.js"));
Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "SilverlightModule_main", (this.TemplateSourceDirectory + "/Page.xaml.js"));

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), string.Format("createSilverlight{0}", Convert.ToString(ModuleId)), CreateSilverlight());

lrlSilverlight.Text = string.Format("createSilverlight{0}()", Convert.ToString(ModuleId));
}

catch (Exception exc)
{ // Module failed to load

Exceptions.ProcessModuleLoadException(this, exc);
}

}

#region CreateSilverlight

private string CreateSilverlight()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();

sb.Append("<script type='text/javascript'> ");
sb.Append(string.Format("function createSilverlight{0}() ", Convert.ToString(ModuleId)));
sb.Append("{ ");
sb.Append("var scene = new SilverlightModule.Page(); ");
sb.Append("Silverlight.createObjectEx(");
sb.Append("{ ");
sb.Append(string.Format("source: '{0}', ", (this.TemplateSourceDirectory + "/Page.xaml")));
sb.Append(string.Format("parentElement: document.getElementById('dnn_ctr{0}_View_SilverlightControlHost'), ", Convert.ToString(ModuleId)));
sb.Append(string.Format("id: '{0}', ", Convert.ToString(ModuleId)));
sb.Append("properties: { ");
sb.Append("width:'100%', ");
sb.Append("height:'100%', ");
sb.Append("version: '1.0' ");
sb.Append("}, ");
sb.Append("events: { ");
sb.Append("onLoad: Silverlight.createDelegate(scene, scene.handleLoad) ");
sb.Append("} ");
sb.Append("});} ");

sb.Append("if (!window.Silverlight) ");
sb.Append("window.Silverlight = {}; ");
sb.Append("Silverlight.createDelegate = function(instance, method) { ");
sb.Append("return function() { ");
sb.Append("return method.apply(instance, arguments); ");
sb.Append("} ");
sb.Append("} ");

sb.Append("</script> ");
return sb.ToString();

}

#endregion

}
}

Save the page and select Build from the menu bar and then Build Page. The page should build without errors.

Create the module definition

Navigate to the DotNetNuke site using the web browser and log in as the Host account. From the Host menu, select Module Definitions.

From the Module Definitions menu select Create Module Definition.

Enter "SilverlightModule" for Module Name, Folder Name, Friendly Name, and Description. Then click the Create link.

Next, enter "SilverlightModule" for New Definition and click the Add Definition link.

 Click the Add Control link.

On the Edit Module Control page enter "SilverlightModule" for Title, select the DesktopModules/SilverlightModule/View.ascx from the Source drop-down, ensure that Type is set to View and click the Update link.

Navigate to a page in the DotNetNuke site, and from the administration menu, select SilverlightModule from the Module drop-down and click the Add link.

The module will now appear.

You can download the module and source code here: SilverlightModule_01.00.00_Install.zip

The DotNetNuke module explained

The DotNetNuke module required you to replace the Default.html, and the Default_html.js files with the View.ascx and View.ascx.cs files. The files provide the same functionality except that the DotNetNuke files provide this functionality dynamically.

The entry point for the DotNetNuke module is this code in the View.ascx file:

<asp:Panel ID="SilverlightControlHost" runat="server" Height="400px" Width="400px">

<script type="text/javascript">
<asp:Literal ID="lrlSilverlight" runat="server"></asp:Literal>
</script>

</asp:Panel>

The ASP.NET Panel control causes a DIV to be created at run-time. The ASP.NET Literal control will also be replaced at run-time with the words "createSilverlight" and the module number appended to it to make the call unique. This is necessary because there may be other Silverlight modules on the page and you would not want to inadvertently call the wrong code.

The View.ascx.cs file contains this code to reference the .js files needed for the application.

Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "Silverlight", (this.TemplateSourceDirectory + "/Silverlight.js"));
Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "SilverlightModule_main", (this.TemplateSourceDirectory + "/Page.xaml.js"));

The following line causes a dynamically created JavaScript method to be created and referenced:

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), string.Format("createSilverlight{0}", Convert.ToString(ModuleId)), CreateSilverlight());

The following lines cause the parameters to be dynamically generated for each module instance:

sb.Append(string.Format("function createSilverlight{0}() ", Convert.ToString(ModuleId)));
sb.Append("{ ");
sb.Append("var scene = new SilverlightModule.Page(); ");
sb.Append("Silverlight.createObjectEx(");
sb.Append("{ ");
sb.Append(string.Format("source: '{0}', ", (this.TemplateSourceDirectory + "/Page.xaml")));
sb.Append(string.Format("parentElement: document.getElementById('dnn_ctr{0}_View_SilverlightControlHost'), ", Convert.ToString(ModuleId)));
sb.Append(string.Format("id: '{0}', ", Convert.ToString(ModuleId)));

DotNetNuke is the perfect "back end" to Silverlight

This example demonstrates how easy it is to integrate Silverlight and DotNetNuke. While Silverlight 1.1 promises more abilities, this comes at a cost, the code will run in the memory on the users computer. Some computers may not be able to handle complex applications.

By using moving as much processing to the web server by using DotNetNuke, you can create light, fast, and efficient applications. Web services play an important part of this strategy. See http://dnnsilverlight.adefwebserver.com for examples of using secure web services to create powerful scalable solutions.

 Print   

Download Code

SilverlightModule.zip (normal Silverlight application)

SilverlightModule_01.00.00_Install.zip (DotNetNuke module)

SilverlightModule.zip (normal Silverlight application)

SilverlightModule_01.00.00_Install.zip (DotNetNuke module)

 Print   

Terms Of Use | Privacy Statement | Copyright 2007-2008 by Adefwebserver.com Dynnamite DotNetNuke Skins & Modules