Working with Silverlight and the ArcGIS Server Web ADF for Microsoft .NET
Microsoft Silverlight delivers the next generation of .NET based media experiences and rich interactive applications for the Web. In this article we will discuss how to augment the user experience of your existing ArcGIS Server .NET Web ADF applications by embedding Silverlight UI components. We will also discuss how you can add GIS capabilities to any Silverlight based site by integrating it with the .NET Web ADF components.
Silverlight 2 allows for a number of features, including but not limited to:
- Calling .NET code from JavaScript
- Calling JavaScript functions from .NET code
- Manipulating the XAML render tree using JavaScript
In this post you’ll explore each of these features, and the classes within the System.Windows.Browser namespace that empower this functionality.
Try it live
Download the full project including test Web site
You need to install the following applications and components to work with the solution provided in this post:
Exposing .NET Functions to the Browser
Within the project directory you will find a .NET solution named ADFinSL. Open the solution using Visual Studio 2008 and run it. You will see a screen like what is shown in Figure 1. The list at the top left is a Silverlight object. Underneath it are three HTML Input controls (buttons) and to the right is a Web ADF Map control. Pressing a button will update the Silverlight content with cities in the selected country.

Figure 1. Running the Project
Understanding the Silverlight .NET Code and XAML
The Silverlight content in Figure 1 uses XAML (in Page.xaml) to define a ListBox item template which contains TextBlocks bound to the name of a city and latitude and longitude values.
<ListBox x:Name="_cities" Cursor="Hand" SelectionChanged="_cities_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="mySP" Orientation="Horizontal">
<Image Source="pin.png"></Image>
<TextBlock x:Name="textBlock1"
Foreground="Black" Cursor="Hand"
FontSize="14" Height="25"
Text="{Binding CityName}"></TextBlock>
<TextBlock Height="0" Text="{Binding Latitude}"></TextBlock>
<TextBlock Height="0" Text="{Binding Longitude}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: The Latitude and Longitude values are hidden by specifying the height=0.
The Code-Behind contains a Class that is used to represent Cities, and contains a member element named CityName.
public class CityData
{
public string CityName { get; set; }
public double Latitude{ get;set; }
public double Longitude{ get;set; }
public CityData(string cityName, double nLatitude, double nLongitude)
{
CityName = cityName;
Latitude = nLatitude;
Longitude = nLongitude;
}
}
The _getCities member function will return a List<CityData> containing several cities for a given country. Note: This is hardcoded for demo purposes.
Here’s an example of adding city data for the ‘United Kingdom’.
switch (country)
{
case "United Kingdom":
{
ret.Add(new CityData("London", 51.5, 0));
ret.Add(new CityData("Stratford-Upon-Avon", 52.3, -1.71));
ret.Add(new CityData("Edinburgh", 55.95, -3.16));
break;
}
. . .
To bind these results to the ListBox, we simply build the List<CityData> and set it to the ItemsSource property of the ListBox. (‘_cities’ is the name of the ListBox)
public void UpdateCities(string country)
{
List<CityData> myCities = _getCities(country);
_cities.ItemsSource = myCities;
. . .
This function is available to .NET code, but how do we expose it to the browser?
Exposing a .NET method to JavaScript
To expose your .NET code to the browser, you will need to:
- Reference System.Windows.Browser in your code behind.
- Add a Loaded event handler to your page. You can add this in the Page() constructor.
- Implement the Page_Loaded event handler, and use it to register your Silverlight control as a scriptable object. In this case we registered the scriptable object (not to be confused with the Silverlight object itself) as MySilverlightObject
The code looks like:
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
upDateCities("United Kingdom");
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.RegisterScriptableObject("MySilverlightObject", this);
}
Once you’ve done this you can now register your Public methods to be scriptable by using the [ScriptableMember] attribute.
[ScriptableMember]
public void UpdateCities(string country)
{
List<CityData> myCities = _getCities(country);
_cities.ItemsSource = myCities;
. . .
Calling the .NET Method from JavaScript
The first thing you should make sure of is that the Silverlight object has an ID. This is needed so that JavaScript can get a reference to it.
<object data="data:application/x-silverlight,"
type="application/x-silverlight-2-b2"
width="300" height="400" id="slControl" VIEWASTEXT>
...
</object>
Now JavaScript can get a reference to your Silverlight control based on this ID:
var slPlugin = document.getElementById("slControl");
To call the .NET based method you then use the syntax:
<PluginID>.content.<ScriptableObjectName>.method(parameters)
The JavaScript function called ChangeCountry(country) does this:
function ChangeCountry(country)
{
var slPlugin = document.getElementById("slControl");
slPlugin.content.MySilverlightObject.UpdateCities(country);
}
The HTML Input buttons call this and pass the relevant country.
<input id="bUK" style="width: 100px" type="button"
value="United Kingdom" onclick="doCities('United Kingdom');" NAME="bUK"/>
<input id="bGermany" style="width: 100px" type="button"
value="Germany" onclick="doCities('Germany');" NAME="bGermany"/>
<input id="bFrance" style="width: 100px" type="button"
value="France" onclick="doCities('France');" NAME="bFrance"/>
When the user presses an HTML button, the JavaScript function doCities will execute. This calls the Silverlight scriptable object and passes the parameter to the UpdateCities method in the .NET code for the SilverLight control. The parameter is used to create a List<CityData> of cities for the selected country, which will then be bound to and displayed in the ListBox.
Further Study
In the this section, you saw how to access the .NET code from within JavaScript, but in addition to this you can also manipulate the XAML that Silverlight renders using JavaScript in the browser. Furthermore, Silverlight isn’t restricted to the XAML that is defined as part of the Visual Studio / Blend project. It can be dynamically added and removed at runtime from within JavaScript too!
Here’s some good material for further review:
http://msdn.microsoft.com/en-us/library/cc645076(VS.95).aspx
Calling Browser Script from .NET
Thus far we’ve seen how you can call .NET code from JavaScript within the browser – but what about the other way? The Web ADF has a public JavaScript interface, so instead of building your own Silverlight host for the Web ADF, it’s much easier to have Silverlight call out to the browser and use JavaScript to interact with the Web ADF Map control.
Earlier you saw that pressing HTML buttons that represent different countries will cause cities from those countries to be loaded into the Silverlight content. When you select a city name (in the Silverlight control) it will call a JavaScript function that locates the selected city on the map based on its latitude and longitude.
You can see it in Figure 2.

Figure 2. Calling the browser from Silverlight in order to use the Web ADF
Note that the XAML ListBox binds to the CityName, Longitude and Latitude. The latter elements are ‘hidden’ by setting their height value to ‘0’.
Note also that the SelectionChanged Event handler is wired up to the ListBox that contains the TextBlock elements. This means that every time the selection changes, the event will be captured and the values of the selected CityData item can be derived, allowing us to pull the Name, Latitude and Longitude of the current city.
Let’s take a look at this event handler.
private void _cities_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_cities.SelectedItem == null)
return;
CityData cd = _cities.SelectedItem as CityData;
ScriptObject myScriptMethod =
(ScriptObject)HtmlPage.Window.GetProperty("GotoCity");
myScriptMethod.InvokeSelf(cd.Latitude, cd.Longitude);
}
Working with the ScriptObject is where the fun begins.
The HtmlPage class allows us to get a reference to a JavaScript function by invoking its Window.GetProperty method and passing it the name of the function. This has to be cast as a ScriptObject in order to be callable:
ScriptObject myScriptMethod = (ScriptObject)HtmlPage.Window.GetProperty("GotoCity");
Now you can call the function using InvokeSelf and pass it the appropriate parameters:
myScriptMethod.InvokeSelf(cd.Latitude, cd.Longitude);
Of course the function GotoCity has to exist on the page, and it has to match the signature that is being used to call it.
Here’s the JavaScript function that takes latitude and longitude and centers and zooms the Web ADF map on these coordinates. Note that Web ADF JavaScript components, which includes the map client control (a scriptable server control), are used to manipulate the map and its contents.
function GotoCity(latitude, longitude) {
// if map does not exist, get it
if (map == null)
GetMap();
// if graphic exists, remove first
if (graphics)
map.removeGraphic(graphics);
// mark location
var sym = new ESRI.ADF.Graphics.MarkerSymbol("images/pin.png", 16, 32);
var point = new ESRI.ADF.Geometries.Point(longitude, latitude);
var feature = new ESRI.ADF.Graphics.GraphicFeature(point, sym);
map.addGraphic(feature);
graphics = feature;
// Zoom to Envelope using Lat/Long
var env =
new ESRI.ADF.Geometries.Envelope(
longitude - 0.05, latitude - 0.05,
longitude + 0.05, latitude + 0.05);
map.zoomToBox(env, true);
}
Further study
In addition to calling JavaScript functions, you can also use .NET code to manipulate HTML elements.
Retrieve the HtmlElement using the element name in a call to HtmlPage.Document.GetElementByID(‘elementName’).
Manipulate the element by calling the ‘setAttribute’ method and providing an attribute name and value: element.setAttribute(“attributeName”, value);
Deploying the Silverlight Web Application to your Web Server
Now that you have a built application, you may be wondering what it might take to deploy the ASP.NET application with Silverlight content. Well, there are several ways to deploy the application, all of which are described on the Microsoft ASP.NET and Silverlight Web Sites. Let me describe a couple of them for you.
Pre-compiled Web Site
First, in Visual Studio, you can right-click on the web application project and select the “Publish Web Site” menu item.

Figure 3: Publish Web Site Menu item from a right-click context menu
A dialog will appear that will ask some questions and then you'll click OK to deploy.

Figure 4: Publish Web Site Dialog Box
XCOPY Deployment
Another option is the old copy and paste or XCOPY deployment. Simply copy your web application files (SLADFIntegrationWeb) to the production server hard drive and use Internet Information Services Manager to configure a virtual directory as a Web application.
Final notes
In both cases, you may need to add a MIME type to support the Silverlight content. The following web site discusses those steps in detail:
http://blogs.msdn.com/tims/archive/2008/03/18/configuring-a-web-server-to-host-silverlight-content.aspx
Other Web Sites to further your study on ASP.NET and Silverlight Deployment options are:
ASP.NET Deployment Overview
Walkthrough: Deploying an ASP.NET Web Application using XCOPY
That’s it! Enjoy!
Contributed by Arthur Haddad of the ArcGIS Server .NET development team