This article is compatible with the latest version of Silverlight.
Introduction
Silverlight helps for creating Rich Internet Applications (RIAs). It runs in the context of the browser. There is an isolated area, called sandbox, which holds the Silverlight application. But why is it necessary to restrict the Silverlight applications in such a way? The answer of this question is pretty simple - because of the security. Running such applications locally is dangerous. They may damage your computer or your data. So, there is a necessity to somehow restrict them. Thus, a Silverlight application runs in the sandbox. In this way it has the following restrictions:
- Silverlight does not have direct access to the file system. It only has access to the isolated storage area, where it can store data. This area is limited. Initially, it has size of 1MB per web site. It is possible to increase the size of this area after the user agreement.
- There is no way to open dialogs like Open/Save. You can use the browser Open dialog (OpenFileDialog).
- You have no direct access to the local resources like printers. You can use JavaScript to print your page (further in this article I will demonstrate how you can achieve this).
Well, Silverlight runs in the context of the browser. Thus, it runs locally and you cannot work synchronously with the server. What does it mean? Let’s have a look at the following diagram:
When the browser sends a request to the server, the server executes the application code synchronously method by method. When the execution of the code is over, the server sends a response to the browser.
In this way, Silverlight can only execute the code locally. The only way to contact the server is via asynchronous calls (like AJAX technology does). However, Silverlight can easily communicate with other similar technologies, which also run locally - Flash, JavaScript, VBScript, etc. Furthermore, these technologies can communicate with Silverlight, too. Well, I am not telling you that this is simple, but it is possible.
Accessing the HTML DOM
Not only that Silverlight can communicate with JavaScript, but it can access the HTML DOM (Document Object Model) very easily. What is the HTML DOM? HTML itself is a XML file with initially defined set of tags. The HTML DOM defines a standard way for accessing and manipulating HTML documents. It has a tree structure.
When you want to be able to access a specific element from this tree structure, you should specify an ID attribute. This ID should be unique in order to access the specified element. If there are two or more element with equal IDs, you will encounter a problem when you want to access some of them. If you want, mark a group of elements as identical; you should specify the class attribute to each of them.
In Silverlight you can interact directly with the HTML DOM. This can be done through the HtmlPage.Document object. The HtmlPage class permits access to, and manipulation of, the browser's Document Object Model. Through this class you can also access other browser features like browser information. This class is located in the System.Windows.Browser namespace.
HtmlDocument = HtmlPage.Document;
HtmlPage.Document returns an object of type HtmlDocument. With this object you can easily access the HTML DOM.
private void SendMessage(string message)
{
HtmlDocument doc = HtmlPage.Document;
HtmlElement element = doc.GetElementById("message");
if (element != null)
{
element.SetProperty("innerHTML", message);
}
}
Here is the result. You can see the online demo.
The HtmlDocument class provides a great variety of methods and properties to manage the HTML document. Let’s have a look at some of them:
- Body - Accesses the body of the document. As the body is a regular HTML element, you can change its attributes, children elements, etc.
- Cookies - Gets or sets the cookie information for the current site. This is very helpful when you want to set a flag if an action is done. When you reload the page, the server can read this flag and perform some specific action.
- QueryString - Gets the query string collection for the current site. In this way you can display different content based on a specified query string key, for example.
- GetElementById(...) - Gets an element by its ID. This is the method that I used in the previous example. If you want to get a specific element, just set its ID and use this method instead of going through the whole collection of elements.
- GetElementsByTagName(...) - Gets a collection of elements with an identical tag name. With this method you can perform an action over a group of elements (for example, links or SPANs).
The other important class is HtmlElement. Here are some of its interesting methods and properties:
- Children - Gets all children elements of the current one. This property lets you go through the collection of all sub elements of a specific one.
- CssClass - Gets or sets the class attribute of an element. You can very easily manipulate the styles of the elements.
- SetAttribute(...) - Changes the value of an attribute of the current element. You can change its value, for example.
- SetProperty(...) - Changes the value of a property of the element. What is the difference between this method and the previous one? Well, each element has properties (specified by the DOM). These properties are accessible through JavaScript or any other scriptable language, which runs in the browser. With Silverlight you can also access these properties with this method. Attributes are used in the HTML declaration. For each attribute there is a property.
- SetStyleAttribute(...) - Changes a style attribute of the element. You can change its display mode, for example. (display = "none").
As you can see, Silverlight lets you access and modify the HTML DOM very easily.
Call JavaScript functions
Well, modifying the HTML DOM is very interesting and helpful. But what if I want to call a JavaScript function? For example, I have a JavaScript function, which performs a lot of visual actions. I do not want to use Silverlight to modify the HTML DOM, because I want to reuse this functionality. So, I need to find a way to interact with JavaScript.
For our convenience, Silverlight lets you call JavaScript functions. This process is very simple. You have to use the HtmlPage.Window object to invoke your JavaScript function. This object is of type HtmlWindow. It lets you interact with the browser windows. You can show alert or prompt boxes, you can attach or detach events, etc. One of its greatest functionalities is the Invoke() method, which allows us to call JavaScript functions. Here is the example:
Silverght:
private void Button_Click(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke("showMessage", "Hello!");
}
JavaScript:
function showMessage(message) {
alert(message);
}
Here is the result. You can see the online demo.
Accessing a Silverlight application from JavaScript
This process is straight forward. You need to accomplish the following things to let your Silverlight application be accessed from JavaScript.
- In the constructor you should make call to the RegisterScriptableObject() method. It accepts two parameters:
- A name, which you will use when you make calls to your application. You can call this method many times in order to register many classes.
- An object, which will be called.
- You can call only public methods in your Silverlight application. If you want a method to be accessed from JavaScript, you have to add the ScriptableMember attribute before the method declaration.
Finally, you can call your defined methods from JavaScript directly in this way:
var control = document.getElementById("SilverlightControlId");
control.Content.RegisteredObjectName.MethodName(parameters);
Here is an example:
Silverlight:
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject("Page", this);
}
[ScriptableMember]
public void Start()
{
// do something
}
[ScriptableMember]
public void Stop()
{
// do something
}
}
JavaScript:
var slcontrol = document.getElementById("<%= slControl.ClientID %>");
function start() {
if (slcontrol) {
slcontrol.Content.Page.Start();
}
}
function stop() {
if (slcontrol) {
slcontrol.Content.Page.Stop();
}
}
Here is the result. You can see the online demo.
Don’t forget that you have to give your Silverlight control a proper ID in order to access it from JavaScript. You can do this by setting its ID attribute. If you use ASP.NET Silverlight tag, don’t forget that the control’s ID on the client browser can be obtained from the Silverlight control’s ClientID property.
<asp:Silverlight ID="mySlControl" ... />
<script type="text/javascript">var control = document.getElementById("<%=mySlControl.ClientID %>");
</script>
If you need to have a greater interaction between Silverlight and JavaScript, you can register as many scriptable objects as you want.
Silverlight and Flash
Communication between Silverlight and Flash isone very interesting topic. As you cannot directly access a Flash content from your Silverlight application, you can process the communication through JavaScript. In my following articles I will demonstrate how you can achieve this.
Source Code
You can download the source code of each of the examples in the article.
References
- http://www.w3schools.com/HTMLDOM/default.asp
- http://silverlight.net/blogs/msnow/archive/2008/10/06/silverlight-tip-of-the-day-56-accessing-the-html-dom-from-silverlight.aspx
- http://silverlight.net/blogs/msnow/archive/2008/07/08/tip-of-the-day-15-communicating-between-javascript-amp-silverlight.aspx