Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Blending HTML into Silverlight pages seamlessly

0.00/5 (No votes)
8 Feb 2009 1  
This article will show a technique to blend an HTML page into a Silverlight page seamlessly through .NET/JavaScript interop and HTML frames.

Introduction

The scenario that this article solves is the following: I am developing a simple image viewer page with a menu on the top-left. The menu is developed using Silverlight. By clicking the menu button, users can view a resizable image on the main page. In addition to showing an image, I also want the main page to be able to show an HTML content. Moreover, I want to use a Silverlight control to show the image or the HTML content.

There are two issues to be solved:

  1. There is no existing HTML Silverlight control that can render an HTML page.
  2. How to route the OnClick event from the Menu control to the Image control.

In the following sections, I will show you an idea of solving the above problems.

I assume readers are familiar with ASP.NET/C#, Silverlight, Visual Studio, JavaScript, and DHTML.

Background

Calling a JavaScript function from .NET

Calling JavaScript from .NET code can be achieved through the HtmlPage.Window.Invoke(name, param object[] args) function of the System.Windows.Browser namespace.

Example of calling a JavaScript function Foo() from a C# function CallFooFromCSharp():

C#/Silverlight code:

using System.Windows.Browser;

class FooClass
{
    public void CallFooFromCSharp()
    {
        HtmlPage.Window.Invoke("Foo", "Hello World");
    }
}

JavaScript code:

<script type="text/javascript">
function Foo(text) {
    alert(text);
}
</script>

Calling a .NET/Silverlight function from JavaScript

The converse to calling a JavaScript function from .NET can be achieved by first obtaining the Silverlight object and then calling the function using object.Content.[ObjectName].[FunctionName].

Example of calling a C# function Foo() from a JavaScript function CallFooFromJavascript():

C#/Silverlight code:

using System.Windows.Browser;

class FooClass
{
    [ScriptableMember]
    public void Foo()
    {
        // do something
    }
}

JavaScript code:

<script type="text/javascript">
function CallFooFromJavascript() {
    var svlObject = document.getElementById("silverlightControl");
    svlObject.Content.FooClass.Foo();
}
</script>

Working with the HTML FrameSet

An important knowledge that we need to know about working with the FrameSet is how we:

  • Get a frame object:
  • var parentFrame = parent.frames['']
  • Calling a JavaScript function GetMainFrame() in the parent frame:
  • parent.GetMainFrame()
  • Calling a JavaScript function on one frame from a function in another frame:
  • var mainFrame = parent.GetMainFrame();
    mainFrame.Foo();

The code highlights

The HtmlSilverlightBlend.zip attachment contains three projects: ImageBrowser, MyMenu, and SilverlightInterFrameCommunication.Web.

  • The ImageBrowser project contains an ImageBrowser Silverlight control.
  • The MyMenu project contains a MyMenu Silverlight control.
  • The SilverlightInterFrameCommunication.Web contains a test web project with the index.html as the root page where the FrameSet is defined.

The following is the code snippet where the Silverlight menu button click is handled and routed to the JavaScript functions openImage() or openPage().

To show a Silverlight control that shows a particular image, the openImage() function will be called with the image URL specified. The idea is that we will call an ASPX page and pass an image URL as a 'tag' query string. The query string can be accessed from a Silverlight control by calling HtmlPage.Document.QueryString["tag"].

For example, I could pass the following to tell the ImageBrowser control to load an image with tag='A': ImageBrowser.aspx?tag=<A>.

The openPage() function will open a URL. It depends on what the URL value is and also the content served in that URL, but the point here is that you can load a normal HTML page with this approach.

MyMenu.Xaml.cs:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Button sourceBtn = (Button)sender;

   switch (sourceBtn.Name)
    {
        case "Obama":
            HtmlPage.Window.Invoke("openImage", "ImageBrowser.aspx", "obama");
            break;
        case "Gates":
            HtmlPage.Window.Invoke("openImage", "ImageBrowser.aspx", "gates");
            break;
        ...
        case "Microsoft":
            HtmlPage.Window.Invoke("openPage", "http://www.microsoft.com");
            break;
        case "Google":
            HtmlPage.Window.Invoke("openPage", "http://www.google.com");
            break;
    }
}

MyMenu.aspx:

function openImage(url, tag) {
    var imageUrl = url + "?tag=" + tag;

    // open imageUrl at mainFrame
    parent.OpenPage(imageUrl);
    parent.SetFooterCaption("My name is " + tag);
}

function openPage(url) {
    // open url at mainFrame
    parent.OpenPage(url);
    parent.SetFooterCaption("I am browsing " + url);
}

Points of interest

A different technique/discussion of blending an HTML page onto a page that has a Silverlight control has been reported in the Silverlight.net forums. One of the suggested hacky ways mentioned in the forum is to use the Opacity property of the Silverlight control (see below):

"Silverlight does not support hosting HTML (like WPF's Frame element), but that should not be a blocker. There's another way to achieve this. You position your HTML content directly under the Silverlight surface using DIVs. Then, declare the Silverlight plug-in (OBJECT tag) as transparent, plus set IsHitTestVisible="false" on the Silverlight elements. The transparency will ensure that HTML content shows through. You can have elements in Silverlight with opaque colors etc. That's fine. Then, the hit test visibility property ensures that mouse and keyboard events will pass through Silverlight into the HTML surface underneath."

- Ashish Shetty | Program Manager | Microsoft

In this article, we show a different way of solving the issue of blending HTML content with Silverlight content, that is using the .NET/JavaScript interop and the HTML FrameSet.

After reading this article, readers should now feel more comfortable about how the .NET/JavaScript interop works, and learn a technique to route an event from a Silverlight control to another Silverlight control. The example also shows how you can pass and process querystrings to a Silverlight control.

Your feedbacks/comments are appreciated. If you have a different idea of doing this, for example, a 1-page approach without using a FrameSet, let me know as I will be interested in learning your approach. The reason I am using this approach is that I have tried an approach of having more than one Silverlight control in an ASPX page and I found it was not trivial using a div/table to do the layout with more than one Silverlight control.

History

  • Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here