Introduction
This article shows how to integrate dynamically created HTML pages in a
Silverlight application and how to send information from and to both
entities. For example we will create 2 pages to edit and display emails. Have
you ever searched the web for a free WYSIWYG HTML editor to use with
Silverlight? If yes, you'll know what you find: 2 or 3 free RTF user controls
that doesn't produce HTML code as result and some developer tools up from 400
dollars!
Don't search any longer - here's a free solution how to integrate CKEditor
(or any other free HTML editor) in your Silverlight application.
Background
When I started the project, I had an absolute wrong concept in mind, how
Silverlight would interact with HTML. In all samples, found in the web (and
there are only a few), I was looking for the line of code that would specify
the URL of the web page I want to display...hahaha!!
In fact, Silverlight can only access exactly ONE HTML (or ASP) page - namely
the default HTML or ASPX page that is created automatically with your
Silverlight solution in Visual Studio. So all you have to do is: enhance
these page(s) with your own code. Which of these pages will be used depends on
the web.config file at your domain host that will run your application
(default page). If you're not sure, simply keep both page contents identically.
Using the code
Let's start with these default pages - in this example I will show the HTML
version but it's simple to do the same with the ASP page (included in the sample project). First we have to insert two parameters within the body
tag:
<param name="windowless" value="true" />
<param name="onLoad" value="pluginLoaded" />
The first parameter will ensure that HTML content will be visible (otherwise
all HTML content will be hidden behind your Silverlight surface). The second
parameter will cause an event to be fired to the HTML page when your Silverlight
application is loaded (a JavaScript function will handle this event - see below).
Next we need an invisible div
element within the page that will act as
container for the dynamic HTML contents we want to display. Therefore we will
add the following line below the div
with the silverlightControlHost
:
<div id="HTMLContentArea" style="position: absolute; display:none;"></div>
Be sure to add the
div
outside the
silverlightControlHost
- otherwise the
dynamic HTML contents will only be shown in IE compatibility mode!!
Also we have to include some JavaScript functions in the script
area of the page to serve the button clicks and to interact with the Silverlight application. I think everybody will understand these functions so I don't explain them in detail - only this: most functions refer to HTML elements that will be inserted at runtime into our invisible div
container, so don't worry about. You may adapt these functions to other dynamic content you'll probably add to your own solution.
Finally we have to add a reference to the JavaScript file coming with CKEditor and we're done with the HTML part:
<script type="text/javascript" src="ckeditor/ckeditor.js"></script>
(see the sample project for the complete HTML page)
The Silverlight part
This step will lead you through all
necessary code to show and hide any HTML content and how to interact with the JavaScript functions, we placed in the HTML page of our Silverlight solution.
First we have to add a new class to the project that will act as an interface to HTML. All functions that are called from the JavaScript functions within the HTML page must be prefixed with:
<ScriptableMember()> _
Also the class needs two public properties to store the width and height of the available display
area within the browser for later resizing of the dynamic HTML content (these properties will be set from the Load event of the MainPage of our Silverlight application at runtime to reflect the current dimensions);
Public HTMLWidth As Double = 0
Public HTMLHeight As Double = 0
Two public functions (Show_MailEditor
and Show_MailViewer
) will allow to show the mail editor or viewer from any location in your Silverlight code. Show_MailViewer
will take two parameters (subject and body) to be displayed in the mail viewer. Both functions will first create dynamic HTML content, insert it in the invisible div
of the project's HTML page, resize the elements to fit the available display area and finally makes the div
visible (which results in a HTML page overlaying the Silverlight surface in the browser. Because the CKEditor is loaded at runtime, it needs some milliseconds for replacing the assigned textarea
element, so we need a timer to perform a short delay before resizing the editor. At last we need to
explicitly set the focus to one of the elements in our dynamic HTML content - otherwise the input elements will work only on first call and will be frozen on any further call showing the HTML page (don't ask me why...but it works this way!).
To make this interface available from all code locations, create the instance in a global module like this:
Module modGlobal
Public objMailInterface As MailInterface = Nothing
End Module
Now we have to register the interface for scripting for the Silverlight application. Add the following lines of code at the end of the Application_Startup
procedure in App.xaml.vb:
objMailInterface = New MailInterface
HtmlPage.RegisterScriptableObject("MailInterface", objMailInterface)
As mentioned before the application has to signalize the available browser display area to the interface at runtime. To solve this, add the following code to the MainPage_SizeChanged
event in MainPage.xaml.vb
:
objMailInterface.HTMLHeight = Me.ActualHeight
objMailInterface.HTMLWidth = Me.ActualWidth
Now we're ready to call one of our HTML pages from anywhere in the code:
objMailInterface.Show_MailEditor()
objMailInterface.Show_MailViewer("Mail Demo", "<p>Hello World!</p><p>This is a test text...</p>")
Thanks to Hiren Khirsaria for his great article about communication between Silverlight and JavaScript!
To see the code in action download the sample project above and modify it as you like - enjoy!