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

How to add Maps and GIS into Silverlight Applications

17 Jul 2009 1  
ESRI has developed an API to allow you to embed maps and add GIS functionality using online services from ESRI’S ArcGIS Online and Bing Maps for Enterprise. This article will demonstrate how to use ESRI’s ArcGIS API for Microsoft Silverlight/WPF.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Introduction

In the world of geographic information systems (GIS) and maps designed for the Web, users are demanding ever-improved application experiences. Further, the demands of these Web-based GIS applications go beyond supporting a single browser technology or platform. If you are building a Web application today, you need technologies that support not only a way to deliver a more compelling user experience, but also tools that enable you to deliver this experience quickly to multiple browsers and platforms. ESRI has developed an API to consume mapping and GIS components for the Microsoft Silverlight platform called ArcGIS API for Microsoft Silverlight/WPF.

Its primary purpose is to make it simple to create rich mapping with GIS functionality for desktop and Web applications.

The API enables you to integrate services from ESRI’s ArcGIS Server, ArcGIS Online, and Bing Maps for Enterprise. The API provides components to display maps that support multiple map projections, both dynamic and cached (tiled) map services. It also allows the drawing of graphics on top of the map (e.g., multipoint, polyline, polygon, symbols, attributes). For example, a graphic resource could be used to hold polygons drawn by a user or display features that satisfy a user-defined query. Often times, GIS Web applications need to include geospatial functionality that goes beyond simple map display and interaction. For these sorts of functional needs, the API provides a set of task classes to perform common GIS tasks. These classes allow you to easily write application-specific code to extract information from ArcGIS Server services and present that information to your users. For instance, an appliance repair company could use the geoprocessing task to generate drive-time polygons to estimate the total length of services calls. The API includes the following tasks:

  • Query- gets features from map services that satisfy attribute queries.
  • Identify- gets features from map services that intersect a location.
  • Find- gets features from map services that contain a particular value in their attributes.
  • Address locator- gets the location of an address (geocode) or the address of a location (reverse geocode).
  • Network Analysis- calculates routes and display graphical results and directions.

  • Geometry- performs geometric operations such as buffering, projecting calculating areas and lengths, and simplifying.
  • Geoprocessing- does complex GIS analysis by executing geoprocessing models that have been published as geoprocessing services.

Before we dive directly into adding maps and GIS functionality to Silverlight applications, it would be beneficial to understand what GIS is and the importance. GIS allows us to view, understand, question, interpret, and visualize data in many ways that reveal relationships, patterns, and trends in the form of maps, globes, reports, and charts. A GIS helps you answer questions and solve problems by looking at your data in a way that is quickly understood and easily shared.

A GIS can be viewed in three ways:

The Database View: A GIS is a unique kind of database of the world—a geographic database (geodatabase). One way to think of a GIS is as a spatial database containing datasets that represent geographic information in terms of generic GIS data model– features, rasters, attributes, topologies, networks, and so forth.

The Map View: A GIS is a set of intelligent maps and other views that show features and feature relationships on the earth's surface. Maps of the underlying geographic information can be constructed and used as "windows into the database" to support queries, analysis, and editing of the information.

The Model View: A GIS is a set of information transformation tools that derive new geographic datasets from existing datasets. These geoprocessing functions take information from existing datasets, apply analytic functions, and write results into new derived datasets. Geoprocessing involves the ability to string together a series of operations so that users can perform spatial analysis and automate data processing –all by assembling an ordered sequence of operations.

Now that we understand what GIS is, the next step is to add this functionality using tools developed by ESRI.

Tools

You will need the following to work with this example:

The ArcGIS API for Microsoft Silverlight/WPF is free to use for non-commercial use. To use these services externally for commercial purposes, you must purchase an annual subscription to the ArcGIS Web Mapping APIs through ArcGIS Online.

Getting Started

The example below shows how to create a map control and add a geoprocessing task to display drive-time polygons on a map in 1, 2, and 3 minute increments. This application contains two ArcGIS Server tiled (cached) map service layers, street map and imagery from ArcGIS Online. It also contains a custom startup extent to define the initial map extent when the application starts, a navigation tool, progress bar, and a slider control to switch the display between the street map and imagery layer. The following steps assume you are familiar with XAML and C#, you have downloaded the ArcGIS API for Microsoft Silverlight/WPF assemblies and Silverlight toolkit, created a Silverlight application in Visual Studio, and are working in the XAML view of the main page (e.g., Page.xaml) of your application.

Add a reference to the System.Window.Controls.Theming.BureauBlue.dll from the Silverlight Toolkit and declare the namespace as below. This theme will be used for the slider control. To use the ESRI assemblies, add a reference to the ESRI.ArcGIS.Client.dll in your application and add an XML namespace that references the ESRI.ArcGIS.Client namespace. The namespace declarations would appear as below. To display a task’s results, you need to specify an output interface. For displaying the geometry of result features, you will use one GraphicsLayers and three SimpleFillSymbols for the output. Then you will specify MapTips on the GraphicsLayer for displaying results’ attribute. The MapTips will use the DictionaryConverter class to enable binding to attributes for the task results. Add two XML namespaces one each to the map for ESRI.ArcGIS.Client.ValueConverters and ESRI.ArcGIS.Client.Symbols namespaces in the ESRI.ArcGIS.Client assembly. In order to use the navigation tool from ESRI, you will need to reference the ESRI.ArcGIS.Client.Toolkit.dll and declare a namespace. Create the grid row definition as below.

<UserControl x:Class="SilverlightApp.DriveTimes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:theme=
"clr-namespace:System.Windows.Controls.Theming;assembly=System.Windows.Controls.Theming.BureauBlue" 
xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
xmlns:esriConverters="clr-namespace:ESRI.ArcGIS.Client.ValueConverters;assembly=ESRI.ArcGIS.Client"
xmlns:esriToolkit="clr-namespace:ESRI.ArcGIS.Client.Toolkit;assembly=ESRI.ArcGIS.Client.Toolkit">
  <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="200"/>
  </Grid.RowDefinitions>

Declare a PictureMarkerSymbol, three SimpleFillSymbols, and a DictionaryConverter as resources of the root Grid element. Give each a unique name using the “x:Name” attribute exactly like below. You will use these resources later. The PictureMarkerSymbol will be used to show the location clicked on the map to find the drive time areas. The DictionaryConverter allows you to specify binding to a particular Dictionary Key. The SimpleFillSymbols will be used to show the geoprocessing task outputs on the map.

<!—GEOPROCESSING TASK OUTPUT RESOURCES-->
          <Grid.Resources>
            <esriSymbols:PictureMarkerSymbol x:Name="DefaultMarkerSymbol"
                OffsetX="8" OffsetY="8" Source="blackcar.png" />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol1"
                Fill="#77FF9999" BorderBrush="#FFFF9999" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol2" Fill="#77FFFF99"
                BorderBrush="#FFFFFF99" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol3" Fill="#779999FF"
                BorderBrush="#FF9999FF" BorderThickness="2"  />
            <esriConverters:DictionaryConverter x:Name="MyDictionaryConverter" />
        </Grid.Resources>

Insert the Map control element to a container element in the page. In this example the container is a Grid. Use the ESRI.ArcGIS.Client namespace identifier "esri" to define the namespace that contains the Map control. Give the Map control a unique name using the "x:Name" attribute as below. Define a startup extent for the map to show the current area. Use attribute syntax to define the Extent property of the map. The attribute value is a comma-delimited set of four numbers specifying the min x, min y, max x, and max y values. You will also need to specify a handler for the MouseClick event to handle the clicking on the map to initiate the geoprocessing task for drive time polygons. You will implement this handler later. Add the two ArcGIS Server tiled map service layers to the map. The map contains a collection of layers referenced by the Layers property. The ArcGISTileMapServiceLayer element will enable you to reference an ArcGIS Server cached map service that is hosted by ArcGIS Online. Define the Url to the map service endpoint and include a unique id for each layer.

<!-- MAP-->
<esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White" Progress="MyMap_Progress"
    Extent="-122.5009,37.741,-           122.3721,37.8089"
    MouseClick="MyMap_MouseClick" >
    <esri:Map.Layers>
        <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
        Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
        <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
        Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />

In the Map control element declare a GraphicsLayer and assign it an ID of “MyGraphicsLayer”. You will use this ID in your applications’ NET code to get a reference layer to the layer. Note the GraphicsLayer is specified below the MapServerLayer so that they are drawn above the MapServiceLayer at runtime. Within the element of GraphicsLayer, specify a MapTip to display the non-geographic data of the results. Inside the MapTip element, specify the background for the MapTip’s content. You can use a StackPanel and Border nested inside a Grid as shown below. With the container elements configured this way the MapTip will automatically resize to fit its contents. Add a StackPanel with a vertical orientation and a margin equal to 5. Inside the StackPanel add a TextBlock to specify a data binding expression to bind to the graphic feature’s Info attribute. For this, use the DictionaryConverter you declared above. Within the MapTip element, the DataContext is the Attibutes property of the current feature. This property is a Dictionary where the key is a field name and the value is the feature’s attribute value for the field. Since the DictionaryConverter enables binding to a key within a Dictionary and the DataContext within a MapTip element is a Dictionary, the DictionaryConverter can be used to within a MapTip element to specify data binding on field names. Add another TextBlock to bind the graphics feature’s LatLon attribute. You will explicitly add these attributes to the geoprocessing results in the page’s code-behind.

<!-- MAP-->
  <esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White" 
    Progress="MyMap_Progress" Extent="-122.5009,37.741,-122.3721,37.8089"
      MouseClick="MyMap_MouseClick" >
        <esri:Map.Layers>
          <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
           Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
            <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
            Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />
            <esri:GraphicsLayer ID="MyGraphicsLayer">
              <esri:GraphicsLayer.MapTip>
               <Grid Background="LightYellow">
                 <StackPanel Orientation="Vertical" Margin="5">
                   <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
                      ConverterParameter=Info, Mode=OneWay}" HorizontalAlignment="Left" />
                   <TextBlock Text="{Binding Converter={StaticResource MyDictionaryConverter},
                      ConverterParameter=LatLon, Mode=OneWay}" HorizontalAlignment="Left" />
                 </StackPanel>
                 <Border BorderBrush="Black" BorderThickness="1" />
               </Grid>
              </esri:GraphicsLayer.MapTip>
            </esri:GraphicsLayer>
          </esri:Map.Layers>
        </esri:Map>

One of the advantages of using Silverlight and the ArcGIS API for Microsoft Silverlight/WPF is you can add some simple controls to enhance your applications appearance. For example, in the short lines of code below we have added a slider control and a navigation tool to zoom in/out, pan north,east, south, and west. In addition, there is also some instructional text to execute the drive time geoprocessing task and a progress bar to display the availability of the map.

<!-- ESRI NAVAGATION -->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Row="2" >
            <esriToolkit:Navigation x:Name="MyNavigation" Margin="5"/>
        </StackPanel>
<!-- SAMPLE TEXT-->
        <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,15,15,0" >
            <Rectangle Fill="#22000000" RadiusX="10" RadiusY="10" Margin="0,4,0,0" />
            <Rectangle Fill="#775C90B2" Stroke="LightSeaGreen"  RadiusX="10"
                RadiusY="10" Margin="0,0,0,5" />
            <Rectangle Fill="#FFFFFFFF" Stroke="ForestGreen" RadiusX="5" RadiusY="5"
                Margin="10,10,10,15" />
            <TextBlock x:Name="InformationText" 
                Text="Click on map to set location. Drive time areas of 1, 2,
                and 3 minutes will be displayed"
                Width="150" Margin="30,20,30,25" HorizontalAlignment="Left"
                TextWrapping="Wrap" />
        </Grid>
        <!--SLIDER-->
        <theme:BureauBlueTheme HorizontalAlignment="Right" VerticalAlignment="Top" 
            Background="Transparent" >
            <Slider Orientation="Horizontal"  Margin="10,10,10,10" Width="200"
                Minimum="0" Maximum="100" SmallChange="1" LargeChange="5"
                    Value="0" ValueChanged="Slider_ValueChanged"/>
            </theme:BureauBlueTheme>
        <!--PROGRESS BAR-->
        <Grid HorizontalAlignment="Center" x:Name="progressGrid"
            VerticalAlignment="Bottom"  Grid.Row="2"  Width="200"
            Height="20" Margin="5,5,5,5">
            <ProgressBar x:Name="MyProgressBar" Minimum="50" Maximum="100"/>
            <TextBlock x:Name="ProgressValueTextBlock" Text="100%"
                HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </Grid>

Below is the complete code for the XAML portion. In the next steps you will work in C# to execute the geoprocessing task.

<UserControl x:Class="SilverlightApp.DriveTimes"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:theme="clr-namespace:System.Windows.Controls.Theming;
       assembly=System.Windows.Controls.Theming.BureauBlue"     
   xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
    xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;
      assembly=ESRI.ArcGIS.Client"
    xmlns:esriConverters="clr-namespace:ESRI.ArcGIS.Client.ValueConverters;
      assembly=ESRI.ArcGIS.Client"
    xmlns:esriToolkit="clr-namespace:ESRI.ArcGIS.Client.Toolkit;
      assembly=ESRI.ArcGIS.Client.Toolkit">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="200"/>
        </Grid.RowDefinitions>
        <!-- GEOPROCESSING TASK OUTPUT RESOURCES-->
        <Grid.Resources>
            <esriSymbols:PictureMarkerSymbol x:Name="DefaultMarkerSymbol" OffsetX="8"
              OffsetY="8" Source="blackcar.png" />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol1" Fill="#77FF9999"
              BorderBrush="#FFFF9999" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol2" Fill="#77FFFF99"
              BorderBrush="#FFFFFF99" BorderThickness="2"  />
            <esriSymbols:SimpleFillSymbol x:Name="FillSymbol3" Fill="#779999FF"
              BorderBrush="#FF9999FF" BorderThickness="2"  />
            <esriConverters:DictionaryConverter x:Name="MyDictionaryConverter" />
        </Grid.Resources>
        <!-- MAP-->
        <esri:Map x:Name="MyMap"  Grid.RowSpan="2" Background="White"
            Progress="MyMap_Progress" Extent="-122.5009,37.741,-122.3721,37.8089"
            MouseClick="MyMap_MouseClick" >
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"  Opacity="1"
                  Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
                <esri:ArcGISTiledMapServiceLayer ID="ImageryLayer" Opacity="0"
                 Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer" />
                <esri:GraphicsLayer ID="MyGraphicsLayer">
                    <esri:GraphicsLayer.MapTip>
                        <Grid Background="LightYellow">
                            <StackPanel Orientation="Vertical" Margin="5">
                                <TextBlock Text="{Binding Converter={
                                  StaticResource MyDictionaryConverter},
                                  ConverterParameter=Info, Mode=OneWay}"
                                  HorizontalAlignment="Left" />
                                <TextBlock Text="{Binding Converter={
                                  StaticResource MyDictionaryConverter},
                                  ConverterParameter=LatLon, Mode=OneWay}"
                                  HorizontalAlignment="Left" />
                            </StackPanel>
                            <Border BorderBrush="Black" BorderThickness="1" />
                        </Grid>
                    </esri:GraphicsLayer.MapTip>
                </esri:GraphicsLayer>
            </esri:Map.Layers>
        </esri:Map>
                <!-- ESRI NAVAGATION -->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Row="2" >
            <esriToolkit:Navigation x:Name="MyNavigation" Margin="5"/>
        </StackPanel>
    <!-- SAMPLE TEXT-->
        <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,15,15,0" >
            <Rectangle Fill="#22000000" RadiusX="10" RadiusY="10" Margin="0,4,0,0" />
            <Rectangle Fill="#775C90B2" Stroke="LightSeaGreen"  RadiusX="10"
               RadiusY="10" Margin="0,0,0,5" />
            <Rectangle Fill="#FFFFFFFF" Stroke="ForestGreen" RadiusX="5" RadiusY="5"
               Margin="10,10,10,15" />
            <TextBlock x:Name="InformationText"
               Text="Click on map to set location. Drive time areas of 1, 2,
               and 3 minutes will be displayed"
                Width="150" Margin="30,20,30,25" HorizontalAlignment="Left"
                TextWrapping="Wrap" />
        </Grid>
        <!--SLIDER-->
        <theme:BureauBlueTheme HorizontalAlignment="Right" VerticalAlignment="Top"
            Background="Transparent" >
            <Slider Orientation="Horizontal"  Margin="10,10,10,10" Width="200"
                Minimum="0" Maximum="100" SmallChange="1" LargeChange="5"
                    Value="0" ValueChanged="Slider_ValueChanged"/>
            </theme:BureauBlueTheme>
        <!--PROGRESS BAR-->
        <Grid HorizontalAlignment="Center" x:Name="progressGrid"
            VerticalAlignment="Bottom"  Grid.Row="2"  Width="200" Height="20"
            Margin="5,5,5,5">
            <ProgressBar x:Name="MyProgressBar" Minimum="50" Maximum="100"/>
            <TextBlock x:Name="ProgressValueTextBlock" Text="100%"
               HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </Grid>
    </Grid>
</UserControl>

Executing the Task

In the applications’s XAML, you declared the MyMap_MouseClick method as a handler for Map’s MouseClick event. Now you will implement this handler in the page’s code-behind. When you are done, the handler will display an icon at the clicked location, instantiate the task and configure its input parameters, and execute the geoprocessing task. The task is declared and initialized in the code-behind because tasks alone do not define any user interface, but rather encapsulate pieces of execution logic.

Declare the MyMap_MouseClick method and retrieve the GraphicsLayer for the default display icon and clear it of any previously drawn symbols. Instantiate a new Graphic and set its geometry to be the point clicked on the map and its symbol to be the PictureMarkerSymbol resource that references the Default icon.

  private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
            GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
            graphicsLayer.ClearGraphics();

            Graphic graphic = new Graphic()
            {
                Symbol = DefaultMarkerSymbol,
                Geometry = e.MapPoint,
            };

Specify an attribute of Info, which will allow the values to be bound to a MapTip through XAML you specified earlier. Add the coordinates of the result of the Graphic in an attribute named LatLon. Lastly add the graphic to the GraphicsLayer.

      graphic.Attributes.Add("Info", "Start location");
            string latlon = String.Format("{0}, {1}", e.MapPoint.X, e.MapPoint.Y);
            graphic.Attributes.Add("LatLon", latlon);
            graphic.SetZIndex(1);
            graphicsLayer.Graphics.Add(graphic);

To initialize a geoprocessing task, simply declare a geoprocessor object, instantiate it with the new keyword, and pass the URL of the geoprocessing service’s REST endpoint to the constructor. Specify a handler for the task’s ExecuteCompleted event which will be called when the geoprocessor task is done executing. Also specify a handler for the task’s Failed event, which will trigger if there is a problem executing the task.

//Initialize geoprocessing task
            Geoprocessor geoprocessorTask = new Geoprocessor(
                "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
                "Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons");
            geoprocessorTask.ExecuteCompleted += GeoprocessorTask_ExecuteCompleted;
            geoprocessorTask.Failed += GeoprocessorTask_Failed;

The geoprocessing task’s execution methods take a list of GPParameter objects as input. All the geoprocessing parameter classes (e.g. GPFeatureRecordSetLayer, GPDouble, GPRecordSet, etc.) derive from this class. The CreateDriveTimePolygons service has two input parameters – Input_Location, which is of type GPFeatureRecordSetLayer, and Drive_Times, which is of type of GPString. There are two sets of members for executing and handling the results of a geoprocessing task; synchronously and asynchronously. For this example it will use a synchronous geoprocessing service. When using a service that executes synchronously, you initiate the operation using the ExecuteAsync method. The code to initialize the parameters and ExecuteAsync method for this task is as follows:

//Add parameters to inputs and data types
            List<GPParameter> parameters = new Listlt;GPParameter>();
            parameters.Add(new GPFeatureRecordSetLayer("Input_Location", e.MapPoint));
            parameters.Add(new GPString("Drive_Times", "1 2 3"));
 
            geoprocessorTask.ExecuteAsync(parameters);
        }

Declare a handler for the geoprocessor task’s ExecuteCompleted event. This handler will be invoked when the task is complete. Get a reference to the results GraphicsLayer. The event handler loops through the results features, adding each to a GraphicsLayer. Each GPParameter in the results that are passed to the handler is assumed to be a GPFeatureRecordSetLayer object since this is the output type listed for this task. If a task fails to execute a MessageBox will display the error. The last two methods below implement the logic for the progress bar and slider control.

//Execute the geoprocessing task and draw results when find is complete
        private void GeoprocessorTask_ExecuteCompleted(object sender,
            ESRI.ArcGIS.Client.Tasks.GPExecuteCompleteEventArgs args)
        {
            GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
 
            foreach (GPParameter parameter in args.Results.OutParameters)
            {
                if (parameter is GPFeatureRecordSetLayer)
                {
                    GPFeatureRecordSetLayer gpLayer = parameter as GPFeatureRecordSetLayer;
 
                    List<FillSymbol> bufferSymbols = new List<FillSymbol>(
                    new FillSymbol[] { FillSymbol1, FillSymbol2, FillSymbol3 });
 
                    int count = 0;
                    foreach (Graphic graphic in gpLayer.FeatureSet.Features)
                    {
                        graphic.Symbol = bufferSymbols[count];
                        graphic.Attributes.Add("Info",
                            String.Format("{0} minute buffer ", 3 - count));
                        graphicsLayer.Graphics.Add(graphic);
                        count++;
                    }
                }
            }
        }
    //Notify user if task fails to execute
        private void GeoprocessorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Geoprocessing service failed: " + e.Error);
        }
     //Progess bar visibilty
        private void MyMap_Progress(object sender,
            ESRI.ArcGIS.Client.ProgressEventArgs args)
        {
            if (args.Progress < 100)
            {
                progressGrid.Visibility = Visibility.Visible;
                MyProgressBar.Value = args.Progress;
                ProgressValueTextBlock.Text = string.Format("{0}%", args.Progress);
            }
            else
            {
                progressGrid.Visibility = Visibility.Collapsed;
 
            }
        }
//Display layers in slider
        private void Slider_ValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            MyMap.Layers["ImageryLayer"].Opacity = e.NewValue / 100d;
            MyMap.Layers["StreetMapLayer"].Opacity = 1d - (e.NewValue / 100d);
        }
    }
}

Below is the complete C# code to implement the execution logic for this sample.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Tasks;

namespace SilverlightApp
{
    public partial class DriveTimes : UserControl
    {
        public DriveTimes()
        {
            InitializeComponent();
            MyNavigation.Map = MyMap;
        }


        //Find and mark the location of area when map is clicked
        private void MyMap_MouseClick(object sender,
            ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
            GraphicsLayer graphicsLayer = 
                MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
            graphicsLayer.ClearGraphics();

            Graphic graphic = new Graphic()
            {
                Symbol = DefaultMarkerSymbol,
                Geometry = e.MapPoint,
            };
            graphic.Attributes.Add("Info", "Start location");
            string latlon = String.Format("{0}, {1}", e.MapPoint.X, e.MapPoint.Y);
            graphic.Attributes.Add("LatLon", latlon);
            graphic.SetZIndex(1);
            graphicsLayer.Graphics.Add(graphic);

            //Initialize geoprocessing task
            Geoprocessor geoprocessorTask = new Geoprocessor(
                "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
                "Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons");
            geoprocessorTask.ExecuteCompleted += GeoprocessorTask_ExecuteCompleted;
            geoprocessorTask.Failed += GeoprocessorTask_Failed;

            //Add parameters to inputs and data types
            List<GPParameter> parameters = new List<GPParameter>();
            parameters.Add(new GPFeatureRecordSetLayer("Input_Location", e.MapPoint));
            parameters.Add(new GPString("Drive_Times", "1 2 3"));

            geoprocessorTask.ExecuteAsync(parameters);
        }
        //Draw results when find is complete
        private void GeoprocessorTask_ExecuteCompleted(object sender,
            ESRI.ArcGIS.Client.Tasks.GPExecuteCompleteEventArgs args)
        {
            GraphicsLayer graphicsLayer = 
                MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;

            foreach (GPParameter parameter in args.Results.OutParameters)
            {
                if (parameter is GPFeatureRecordSetLayer)
                {
                    GPFeatureRecordSetLayer gpLayer = parameter as GPFeatureRecordSetLayer;

                    List<FillSymbol> bufferSymbols = new List<FillSymbol>(
                    new FillSymbol[] { FillSymbol1, FillSymbol2, FillSymbol3 });

                    int count = 0;
                    foreach (Graphic graphic in gpLayer.FeatureSet.Features)
                    {
                        graphic.Symbol = bufferSymbols[count];
                        graphic.Attributes.Add("Info", 
                            String.Format("{0} minute buffer ", 3 - count));
                        graphicsLayer.Graphics.Add(graphic);
                        count++;
                    }
                }
            }
        }
        //Notify user if task fails to execute
        private void GeoprocessorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Geoprocessing service failed: " + e.Error);
        }
//Progess bar visibilty
        private void MyMap_Progress(object sender,
            ESRI.ArcGIS.Client.ProgressEventArgs args)
        {
            if (args.Progress < 100)
            {
                progressGrid.Visibility = Visibility.Visible;
                MyProgressBar.Value = args.Progress;
                ProgressValueTextBlock.Text = string.Format("{0}%", args.Progress);
            }
            else
            {
                progressGrid.Visibility = Visibility.Collapsed;

            }
        }
        //Display layers
        private void Slider_ValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            MyMap.Layers["ImageryLayer"].Opacity = e.NewValue / 100d;
            MyMap.Layers["StreetMapLayer"].Opacity = 1d - (e.NewValue / 100d);
        }
    }
}

With the example provided in this article and the flexibility of the ArcGIS API for Microsoft Silverlight/WPF, it is simple and quick to add the power of maps and GIS to your Silverlight applications.

Want to Learn More?

For interactive samples of the ArcGIS API for Microsoft Silverlight/WPF, download the API and visit ESRI’s ArcGIS Server Resource Center. There you will see live samples, documentation, and code to help you get familiar with creating Silverlight applications with the API.

About the Author

ESRI Since 1969, ESRI has been giving customers around the world the power to think and plan geographically. The market leader in GIS, ESRI software is used in more than 300,000 organizations worldwide including each of the 200 largest cities in the United States, most national governments, more than two-thirds of Fortune 500 companies, and more than 7,000 colleges and universities. ESRI applications, running on more than one million desktops and thousands of Web and enterprise servers, provide the backbone for the world’s mapping and spatial analysis. ESRI is the only vendor that provides complete technical solutions for desktop, mobile, server, and Internet platforms.

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