A series of walkthroughs illustrating how to customize the Web Mapping
Application are provided below.
Add a custom tool to the web mapping application
This walkthrough shows how to create a custom tool and add it to the web
mapping application. This tool will allow the user to click on the map to add a
graphic point. To accomplish this customization, do three types of steps.
First, we add a graphics layer to the MapResourceManager control. Second, we
create a class library that contains the code for the tool implementation.
Third, we add the tool to the Toolbar control and use the class library we
created.
-
To start, create a Web application using ArcGIS Manager or ArcIMS Web Manager,
or use the tutorial Creating a Web
application with the template
as a guide.
-
Start Visual Studio 2005 (or Visual Web Developer Express), and use the Start
Page or the File-Open-Website option to open the website you just created. In
the dialog for opening the website, use the Local IIS option to navigate to the
website and open it. The files of the website will display in the Solution
Explorer (see the example at the top of this page).
-
Double-click the Default.aspx page in Solution Explorer to open it. It will
display initially in the HTML code view. Click the Design tab at the
bottom of Visual Studio to switch to design view. The design should resemble
the graphic shown above under the Mapping Page topic.
-
Next we add a graphics layer resource to the map. The graphics layer will
hold the points that the user adds.
-
Click the MapResourceManager1 control on the page to select it. Click the
"smart tag" in the upper right of the control to expose the context menu, and
click Edit Resources to display the MapResourceItem Collection Editor:
Note that you can also open the MapResourceItem Collection Editor from the
properties of the MapResourceManager, under the ResourceItems property.
-
In the MapResourceItem Collection Editor, click Add to add a second resource
item. It will be named MapResourceItem1.
-
With the new resource item highlighted, click in the Name property on the right
side, and rename the resource to graphicsLayer.
-
Click in the Definition property, which displays an ellipsis button (...).
Click the button, which opens a new dialog for the Map Resource Definition
Editor.
-
In the MapResource Definition Editor, click the Type drop-down and select
Graphics Layer. No other properties need to be set for this resource type.
Click OK to dismiss this dialog.
-
Before closing the MapResourceItem Collection Editor, move the graphics layer
to the top of the map control's display. To do this, make sure the graphics
layer item is highlighted in the left side of the dialog. Then click the
up-arrow in the upper middle part of the dialog, which will move the new
resource item to the top, above the map (which is named MapResourceItem0). Your
dialog should resemble the following:
-
Click OK to close the MapResourceItem Collection Editor.
-
Next we will create the class library for the custom tool. We will add this
class library as a code file within the application itself, in the App_Code
directory. ASP.NET 2.0 uses this folder for application-level class libraries.
If you wanted to create a class library to share among many applications, you
would probably author it in a separate Visual Studio project, compile it, and
then you could copy the compiled DLL into the bin directory of the website. We
will just use the application-level approach here.
-
With the website open in Visual Studio 2005 (or Visual Web Developer Express),
right-click in the Solution Explorer on the App_Code folder within the
website. In the menu that pops up, choose Add New Item. The Add New Item dialog
opens. In this dialog, make sure the Class item is highlighted in the Templates
area. For the name, enter GraphicPointTool.vb (if using VB, use the .vb
extension; if using CSharp, use .cs). Make sure the language option is set to
the one in your website -- you can only have one language type in the App_Code
directory and page-behind files. Click OK to add the file and open it in the
editor. Note that the new class is named the same as the file.
-
At the top of the new class file, before the Public Class GraphicPointTool
statement, add these references to your class file. This enables us to use
classes within these namespaces without citing the full path.
[C#]
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.DataSources.Graphics;
using ESRI.ArcGIS.ADF.Web.Display.Graphics;
using ESRI.ArcGIS.ADF.Web.Display.Symbol;
using ESRI.ArcGIS.ADF.Web.Geometry;
using ESRI.ArcGIS.ADF.Web.UI.WebControls;
using ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools;
[VB]
Imports ESRI.ArcGIS.ADF.Web.DataSources
Imports ESRI.ArcGIS.ADF.Web.DataSources.Graphics
Imports ESRI.ArcGIS.ADF.Web.Display.Graphics
imports ESRI.ArcGIS.ADF.Web.Display.Symbol
Imports ESRI.ArcGIS.ADF.Web.Geometry
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools
-
To use our new class as a tool in the mapping application, it must implement
the IMapServerToolAction interface. We must add two items to the class in this
case. First, we add the IMapServerToolAction interface designation to the
class itself. Second, IMapServerToolAction requires the ServerAction method.
Add code to your class for these two requirements (Visual Studio may
insert the method automatically when you add the interface name):
[C#]
public class GraphicPointTool: IMapServerToolAction
{
void IMapServerToolAction.ServerAction(ToolEventArgs args)
{
}
}
[VB]
Public Class GraphicPointTool
Implements IMapServerToolAction
Public Sub ServerAction(ByVal args As ToolEventArgs) Implements IMapServerToolAction.ServerAction
End Sub
End Class
All of the code below will be inserted into the ServerAction method, before the
End Sub or the first closing brace "}".
-
Now we add code inside the ServerAction method to add the graphic point to the
map where the user clicked. The args argument contains the screen location of
the click. We can also get a reference to the Map control from args. Add this
code inside the ServerAction method:
[C#]
// Get a reference to the map from the method argument
Map map = (Map)args.Control;
// Get the point the user clicked from the method argument
PointEventArgs pea = (PointEventArgs)args;
System.Drawing.Point screen_point = pea.ScreenPoint;
[VB]
' Get a reference to the map from the method argument
Dim map As Map = CType(args.Control, Map)
' Get the point the user clicked from the method argument
Dim pea As PointEventArgs = CType(args, PointEventArgs)
Dim screen_point As System.Drawing.Point = pea.ScreenPoint
-
We then convert the pixel coordinates to map coordinates:
[C#]
ESRI.ArcGIS.ADF.Web.Geometry.Point point;
point = ESRI.ArcGIS.ADF.Web.Geometry.Point.ToMapPoint(screen_point.X,
screen_point.Y, map.Extent, map.GetTransformationParams(TransformationDirection.ToMap));
[VB]
Dim point As ESRI.ArcGIS.ADF.Web.Geometry.Point
point = ESRI.ArcGIS.ADF.Web.Geometry.Point.ToMapPoint(screen_point.X, _
screen_point.Y, map.Extent, map.GetTransformationParams(TransformationDirection.ToMap))
-
We will add the point to the GraphicsLayer resource that we created earlier in
the MapResourceManager. However, we cannot add the point directly to the
resource. Instead, we add it to an ElementGraphicsLayer, which is in turn added
to the resource. An ElementGraphicsLayer is a simple type of graphics layer. If
we want more complex interaction with the graphics, we could create a
FeatureGraphicsLayer instead. A FeatureGraphicsLayer behaves similarly to a map
layer. For now, we will use the simpler ElementGraphicsLayer.
We retrieve the ElementGraphicsLayer from the map resource. The first time we
add a point we need to create the ElementGraphicsLayer. Add this code
immediately after the previous code:
[C#]
ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource gResource = null;
// Find the GraphicsLayer resource added to the MapResourceManager
foreach (IGISFunctionality gFunc in map.GetFunctionalities())
{
if (gFunc.Resource is ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)
{
gResource = (MapResource)gFunc.Resource;
}
}
// Find the ElementGraphicsLayer in the graphics resource just found
ElementGraphicsLayer gLayer = null;
foreach (System.Data.DataTable dt in gResource.Graphics.Tables)
{
if (dt is ElementGraphicsLayer)
{
gLayer = (ElementGraphicsLayer)dt;
}
}
// ElementGraphicsLayer will not exist first time a point is added--create it now
if (gLayer == null)
{
gLayer = new ElementGraphicsLayer();
gResource.Graphics.Tables.Add(gLayer);
}
[VB]
Dim gResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = Nothing
' Find the GraphicsLayer resource added to the MapResourceManager
For Each gFunc As IGISFunctionality In map.GetFunctionalities()
If TypeOf gFunc.Resource Is ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource Then
gResource = CType(gFunc.Resource, MapResource)
End If
Next
' Find the ElementGraphicsLayer in the graphics resource just found
Dim gLayer As ElementGraphicsLayer = Nothing
For Each dt As System.Data.DataTable In gResource.Graphics.Tables
If TypeOf dt Is ElementGraphicsLayer Then
gLayer = CType(dt, ElementGraphicsLayer)
End If
Next
' ElementGraphicsLayer will not exist first time a point is added--create it now
If gLayer Is Nothing Then
gLayer = New ElementGraphicsLayer()
gResource.Graphics.Tables.Add(gLayer)
End If
Notice that the ElementGraphicsLayer inherits from the standard .NET DataTable
class. It extends DataTable by adding geometry attributes and more
capabilities.
-
Now that we have the graphics layer object, we can add the point to it. We do
this by creating symbology for the point, and creating a GraphicElement to hold
the point's geometry and symbology. Then we add the GraphicElement to the
graphic layer:
[C#]
// Create the symbology for the point
SimpleMarkerSymbol sms = new SimpleMarkerSymbol(System.Drawing.Color.Red, 20, MarkerSymbolType.Cross);
// Create a graphic element to hold the point and its symbology
GraphicElement ge = new GraphicElement(point, sms);
// Add the graphic element to the graphics layer
gLayer.Add(ge);
[VB]
' Create the symbology for the point
Dim sms As New SimpleMarkerSymbol(System.Drawing.Color.Red, 20, MarkerSymbolType.Cross)
' Create a graphic element to hold the point and its symbology
Dim ge As New GraphicElement(point, sms)
' Add the graphic element to the graphics layer
gLayer.Add(ge)
-
Finally, we refresh the map in order to show the new point. Note that by using
the built-in client callback approach for tools, the map will redraw without
refreshing the entire web page. The code below takes this one step further: if
the browser client is handling the images of the graphics layer and the map
separately (which is the map control default), we only need to refresh the
graphics layer image. This way, the map does not need to be redrawn when we are
only adding the graphic point.
[C#]
if (map.ImageBlendingMode == ImageBlendingMode.Browser)
{
map.RefreshResource(gResource.Name);
}
else
{
map.Refresh();
}
[VB]
If map.ImageBlendingMode = ImageBlendingMode.Browser Then
map.RefreshResource(gResource.Name)
Else
map.Refresh()
End If
Save the class library file.
-
Now we can add the tool to the toolbar. We use the toolbar designer to add the
tool, and point to the class we just created as the server-side action of the
tool.
-
With the website open in Visual Studio 2005 (or Visual Web Developer Express),
open or switch to the Default.aspx page. Switch the view to Design view if
necessary.
-
For the images for the tool, you can use icons included with the developer kit,
typically installed at C:\Program
Files\ArcGIS\DeveloperKit\SamplesNET\Server\data\icons. Copy these icons into
your website by right-clicking on the image folder and choosing Add Existing
Item. Use the add-item dialog to navigate to the sample image folder and add
these images: select_point_1.gif, select_point_1U.gif, and select_point_1D.gif.
Click OK to add these images to the images folder in your website.
-
Click on the Toolbar control to select it. In the Properties window of Visual
Studio, click in the value of the ToolbarItems property, which displays the
ellipsis (...) button. Click this button to open the
ToolbarCollectionEditorForm.
-
In the ToolbarCollectionEditorForm, click the Tool item in the left-hand
Toolbar Items list. Then click the Add button to add a new tool to the toolbar.
-
With the new tool highlighted on the right side of the dialog, click the
Properties arrow-button in the lower right. This expands the dialog to display
the properties of the tool.
-
Set the properties of the tool as follows (you can use the browse buttons to
set the images):
-
DefaultImage = ~/images/select_point_1.gif
-
HoverImage = ~/images/select_point_1U.gif
-
SelectedImage = ~/images/select_point_1D.gif
-
Text = Add Point
-
ClientAction = Point
-
ServerActionAssembly = App_Code
-
ServerActionClass = GraphicPointTool
The ClientAction determines how the user interacts with the map before the
request is sent to the server. "Point" means the when user clicks on the map,
the location is immediately sent to the server. If you created a tool that
required a line or polygon you could choose one of those options.
The ServerActionAssembly is set to App_Code when we include the tool class
within the App_Code folder of the web application. If you created a tool in a
separate project and added the reference to the current website project, you
would use its assembly name instead.
The ServerActionClass is the class within the ServerActionAssembly that
implements the IMapServerToolAction interface. When using the App_Code option,
the drop-down list will not find the class--you must type it in manually.
Your toolbar properties should resemble this graphic:
Click OK to close the toolbar designer.
-
Save the Default.aspx page.
-
View the page in a browser by choosing File-->View in Browser. Test the
tool by clicking the Add Point tool in the toolbar and clicking on the map to
add graphic points to the map.
The flow in this custom tool is summarized in the graphic below. For more
information on callback processing, see AJAX and the
ASP.NET 2.0 Callback Framework.
-
The user activates the Add Point tool in the toolbar, and clicks on the map.
The browser captures the click location.
-
The browser's client ADF code sets up the request to the server via a
client callback (not a full page postback).
-
The browser uses its built-in XMLHTTP object to send the request to the
server without submitting the full page.
-
On the server, the map control receives the callback request and sends the
click location to the custom tool via its ServerAction method. The custom tool
code adds the point to the graphic layer of the map's resources. The response
is generated for the client, which includes information about updating the map
control.
-
The client processes the callback result to update its display.
-
The map control's client-side script determines if any further action is needed
(A-B-C), such as requesting map tiles around the current map, which may be
necessary if the map operation involved moving the map (this is not required in
our particular example of adding a point).
For more examples of adding graphics to the map page, see the samples
Common_AddGraphics and
ArcGIS_AddGraphics in the developer kit samples.
Pass initialization parameters in the URL
This walkthrough shows how to provide initialization parameters in the url
of a Web Mapping Application. In this example, a set of coordinates
with be provided as argument\value pairs in the url for a Web Mapping
Application. The Web application will parse the argument\value
pairs to create an extent. The Web ADF map will display this
extent when the application is first loaded. The same pattern
can be used to define other initialization parameters such as queries, selected
features, and dynamic resources.
-
To start, create a Web application using ArcGIS Manager or ArcIMS Web Manager,
or use the tutorial Creating a Web
application with the template
as a guide.
-
Start Visual Studio 2005 (or Visual Web Developer Express), and use the Start
Page or the File-Open-Website option to open the website you just created. In
the dialog for opening the website, use the Local IIS option to navigate to the
website and open it. The files of the website will display in the Solution
Explorer (see the example at the top of this page).
-
Double-click the Default.aspx.cs file in Solution Explorer to open it. It will
display the code file for the Default.aspx page. The following steps
will involve adding new code to the existing code file. Code that
currently exists in the Web Mapping Application is provided in gray.
Code you need to add is provided in
dark
blue.
-
Add a member variable to store the collection of name-value pairs passed to the
Web application in the url.
[C#]
public partial class WebMapApplication : System.Web.UI.Page, ICallbackEventHandler
{
MapIdentify identify;
public string m_newLoad = "false";
public string m_closeOutCallback = "";
public string m_copyrightCallback = "";
private NameValueCollection queryvalues = null;
-
On initialization of the page, capture the URL parameters using the
Request.QueryString property. Add the Page_Init method with the following
signature and code in the WebMapApplication class:
[C#]
protected void Page_Init(object sender, EventArgs e)
{
if (!IsCallback)
{
queryvalues = Request.QueryString;
}
}
If the request to the page is not a callback (it is a full page postback) then
the url parameters will be interrogated. Since url parameter
information is gathered during page initialization, subsequent page and control
events (during the same request) can work with the query string to change
properties.
-
In this example, a single name-value pair is queried during the prerender event
of the page. The URL should contain the name “Extent” and a value consisting of
a set of comma delimited values to define the extent envelope or a Map control.
Add the Page_PreRender method with the following signature and code in the
WebMapApplication class:
[C#]
protected void Page_PreRender(object sender, EventArgs e)
{
string[] values = queryvalues.GetValues("Extent");
if ((values != null) && (values.Length > 0))
{
string[] extentparams = values[0].Split(',');
ESRI.ArcGIS.ADF.Web.Geometry.Envelope env = new ESRI.ArcGIS.ADF.Web.Geometry.Envelope(Double.Parse(extentparams[0]), Double.Parse(extentparams[1]), Double.Parse(extentparams[2]), Double.Parse(extentparams[3]));
Map1.Extent = env;
Map1.Refresh();
}
}
-
Run the application. In the browser, add the custom name-value pair to the Web
Mapping Application url and reload the page. The format is
“Extent=minx,miny,maxx,maxy”. For example, “Extent=-90,30,-70,50”. Be sure to
include a “?” after the Web Mapping Application path to indicate that a set of
name-values pairs will be provided. The full url may appear as follows:
“http://localhost/WMA/Default.aspx?Extent=-90,30,-70,50”.
Add map coordinate display
This walkthrough shows how to display the coordinate location associated
with the mouse cursor over the map. As the mouse cursor moves
over the map, the browser displays real-time coordinate information in map
units. This walkthrough will add the client-side framework necessary to
store map coordinates in map units on the browser.
-
To start, create a Web application using ArcGIS Manager or ArcIMS Web Manager,
or use the tutorial Creating a Web
application with the template
as a guide.
-
Start Visual Studio 2005 (or Visual Web Developer Express), and use the Start
Page or the File-Open-Website option to open the website you just created. In
the dialog for opening the website, use the Local IIS option to navigate to the
website and open it. The files of the website will display in the Solution
Explorer (see the example at the top of this page).
-
The following steps will involve adding new code to the existing aspx page
and code file. Code that currently exists in the Web Mapping
Application is provided in gray.
Code you need to add is provided in
dark blue.
-
Open the source code view of the Default.aspx page. Add a call to the
getCoords() function to the onload event of the page in the body tag.
<body onload="getCoords()" style="margin: 0px 0px 0px 0px; background-color: white;
width: 100%; font-family: Verdana; font-size: 8pt; color: #A9A9A9; ">
-
Inside the form "form1" add the following javascript and script tag referencing
the display_mapcoords.js in the Web applications JavaScript directory. The
display_mapcoords.js file will be created after this step.
<form id="form1" runat="server">
<script>
function ChangeClient(context)
{
var argument;
if(context == 'GetCoords'){
argument = 'EventArg=GetCoords';
}
<%=m_mapcoordsCallback%>
}
function HandleResponse(returnvalue, ctx)
{
if (ctx == "GetCoords"){
updateCoords(returnvalue);
}
}
</script>
<script language="javascript" type="text/javascript" src="javascript/display_mapcoords.js">
</script>
-
Create a new text file in the Web apps JavaScript folder named
"display_mapcoords.js". Use the following steps to add create and add new
content to the file:
-
In Visual Studio, in the Solution Explorer window, right-click on the
“JavaScript” folder within the Web project and select “Add New Item”.
Select “JScript File” and change name to “display_mapcoords.js”, click Add.
-
Add the following JavaScript content:
var mapminx;
var mapminy;
var mapmaxx;
var mapmaxy;
var mouseX;
var mouseY;
var xDistance;
var iWidth;
var iHeight;
var yDistance;
var mapX;
var mapY;
function getCoords(){
if (mapminx == null){
setTimeout("ChangeClient('GetCoords')", 100);
}
}
function updateCoords(message){
var ext = message.split(":--:");
var map = Maps[ext[0]];
iWidth = map.viewWidth;
iHeight = map.viewHeight;
mapminx = parseFloat(ext[1]);
mapminy = parseFloat(ext[2]);
mapmaxx = parseFloat(ext[3]);
mapmaxy = parseFloat(ext[4]);
xDistance = Math.abs(mapminx - mapmaxx);
yDistance = Math.abs(mapmaxy - mapminy);
setMapMouseMoveFunction(map);
}
function setMapMouseMoveFunction(map){
map.divObject.onmousemove = myOnMouseMove;
map.moveFunction = myOnMouseMove;
map.tempMoveFunction = myOnMouseMove;
}
function myOnMouseMove(e){
e = e || window.event;
getMapXY(client.x, client.y);
window.status = "X: " + mapX.toFixed(2) + " Y: " + mapY.toFixed(2);
}
function getMapXY(xIn,yIn) {
mouseX = xIn;
pixelX = xDistance / iWidth;
mapX = pixelX * mouseX + mapminx;
mouseY = iHeight - yIn;
pixelY = yDistance / iHeight;
mapY = pixelY * mouseY + mapminy;
}
-
Double-click the Default.aspx.cs file in Solution Explorer to open it. It will
display the code file for the Default.aspx page. Add the
following member variable to the WebMapApplication class:
public partial class WebMapApplication : System.Web.UI.Page, ICallbackEventHandler
{
public string m_mapcoordsCallback;
-
Add the following line to the Page_Load method:
protected void Page_Load(object sender, EventArgs e)
{
m_mapcoordsCallback = Page.ClientScript.GetCallbackEventReference(Page, "argument", "HandleResponse", "context", true);
-
In the RaiseCallbackEvent method, add the following iteration to the
switch-case statement when the controlType is "Map":
else if (eventArg == "GetCopyrightText")
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendFormat("///:::{0}:::innercontent:::", "CopyrightTextContents");
int sbLength = sb.Length;
sb.Append(GetCopyrightText());
if (sb.Length == sbLength) sb.Append("No Copyright information available.");
response = sb.ToString();
}
else if (eventArg == "GetCoords")
{
string delimiter = ":--:";
ESRI.ArcGIS.ADF.Web.Geometry.Envelope env = Map1.Extent;
double minx = env.XMin;
double miny = env.YMin;
double maxx = env.XMax;
double maxy = env.YMax;
response = Map1.ID + delimiter + minx + delimiter + miny + delimiter + maxx + delimiter + maxy;
}
break;
default:
break;
-
Handle the ExtentChanged event on the map. Do the following:
-
Open the Default.aspx page in design view.
-
Open the properties page for the Map control and select the Events button
(lightning bolt icon).
-
Double-click in the empty field next to the ExtentChanged property. A new
method named “Map1_ExtentChanged” should be created and the code file for the
page should open to its location.
-
Add the following content to the Map1_ExtentChanged method:
protected void Map1_ExtentChanged(object sender, ExtentEventArgs args)
{
string delimiter = ":--:";
Map map = (Map) sender;
ESRI.ArcGIS.ADF.Web.Geometry.Envelope env = map.Extent;
double minx = env.XMin;
double miny = env.YMin;
double maxx = env.XMax;
double maxy = env.YMax;
string returnstring = Map1.ID + delimiter + minx + delimiter + miny + delimiter + maxx + delimiter + maxy;
string jsfunctioncall = "updateCoords('" + returnstring + "')";
CallbackResult crn = new CallbackResult(null, null, "javascript", jsfunctioncall);
Map1.CallbackResults.Add(crn);
}
-
Run the application. The map coordinates should appear in the browser status
bar as you move the mouse over the map.