Through the Common Data Source API, the Web ADF provides endpoints for retrieving and manipulating data that can be used against any underlying data-source type. The classes of the Common API enable developers to build tools and applications that rely on resources and functionalities of varying data-source types without having to write data-source specific implementations. The following walkthrough will show how to query resources and create graphics showing query results using only the Common API.
This tutorial will provide step-by-step instructions for creating a Web ADF application in Visual Studio 2008 that contains a custom selection tool. This tool will use classes from the Common API to retrieve feature data from a user-specified resource and layer and spatially display this data as a Web ADF GraphicsLayer. Attributes for these features will be displayed in a Web ADF TaskResults control and in callouts (i.e. MapTips) that appear when the mouse passes over a feature on the map. The tutorial also demonstrates the use of ASP.NET AJAX functionality to dynamically update web controls via partial postback. The following Web ADF controls are used in the tutorial: MapResourceManager, Map, Toc, Toolbar, and TaskResults.
Designing the Web application
Our web application will consist of a subset of Web ADF controls that provide basic GIS functionality and several other controls (Web ADF and non-Web ADF) that will be used in conjunction with our custom selection tool implementation. The basic controls include a Map for display of GIS data, a Toc to allow toggling of map layer visibility, a Toolbar to enable interaction with the map, and a MapResourceManager to provide the Web ADF controls access to map services. We will also add a Web ADF TaskResults control to display the attributes of features selected with our custom tool, and two ASP.NET DropDownLists to enable run time specification of the resource and layer to select features from. We will embed the DropDownLists in an ASP.NET AJAX UpdatePanel to allow asynchronous updating of these controls via partial postback, and we will include an ASP.NET AJAX ScriptManager to support asynchronous functionality.
-
Create a new web application using the steps in the
Creating a Web application with the Web controls tutorial. While that
tutorial uses Visual Studio 2005, all the steps except for absolutely
positioning the Toc (step eleven) are the same in Visual Studio 2008. In Visual
Studio 2008, perform this step as follows:
a. In design view, click the Toc control so that it is highlighted.
b. From the Format menu, select “Position…”
c. On the dialog that appears (figure to the right), in the Positioning Style section, select Absolute, then click OK.
- In design view, drag a ScriptManager control from the AJAX Extensions section of the Visual Studio toolbox and drop it in the top left corner of the Default.aspx page, above the Map and MapResourceManager controls. For ASP.NET AJAX functionality to work properly, the ScriptManager must be located on the page before any controls that employ AJAX functionality.
- Drag and drop a Web ADF TaskResults control onto the page. We will use this control to display the attributes of selected features.
- Position the TaskResults control below the Toc. First, make the control absolutely positioned. Do this by using the Visual Studio Position dialog as described in step one. Then, drag the control until it is positioned below the Toc. Expand the width of the control so it is at least 300 pixels wide.
- Set the TaskResults control's BuddyControl property. Select the TaskResults control in design view or in the Properties window, then click the drop-down list for the BuddyControl property. The list will include the names of Map controls available on the page. Select the name of the Map control added previously ("Map1" by default).
- From the AJAX Extensions section of the Visual Studio toolbox, drag an UpdatePanel onto the page and drop it below the toolbar. We will use this to enable AJAX functionality for the two drop-down lists that will specify the resource and layer to select features from.
- Drag a DropDownList control from the Standard section of the Visual Studio toolbox and drop it in the UpdatePanel. On the menu that appears, check the Enable AutoPostBack item. This will make it so that the DropDownList issues a postback when a new item is selected at run time. And because we are placing the control within an UpdatePanel, the postback will be an asynchronous partial postback, rather than a full page postback. This DropDownList will be used to specify the map resource to select features from.
-
Drag and drop another DropDownList into the UpdatePanel. Enable AutoPostBack
for this list as well. We will use this control to specify the layer to select
features from. In design view, the application should appear as shown in the
figure below.
Implementing Page and Control Event Handlers
In configuring our application's user interface, we added two DropDownList
controls to allow users to specify the resource and layer to select features
from, and a TaskResults control to display the attributes of selected features.
The DropDownLists won't contain any items out-of-the-box, so we'll have to
explicitly initialize them with the names of the application's resources and
layers. We also want the layers list to dynamically update any time a new
resource is selected, which will require some code as well. As for the
TaskResults control, since we want to use it to display our custom tool's
results, we need to somehow give our custom tool access to it. We can implement
logic to handle all of these requirements in the Default page's code-behind
class.
- In Solution Explorer, expand Default.aspx and double click on Default.aspx.cs (if you are using C#) or Default.aspx.vb (if you are using Visual Basic) to open Default's code-behind class.
-
We want to add the results from our custom selection tool to the application's
TaskResults control. To be able to do this, we will have to get a reference to
the TaskResults control from within the custom tool's implementation. While
there are a number of ways this can be done, we will use session storage in
this case for simplicity. Store a reference to the control in session by adding
the following code to the handler for the page's Load event. We place the code
here so that when the custom tool is used at run time (which causes the load
event to fire), the reference to the control is updated before execution passes
to the custom tool implementation.
[C#]// Store the TaskResults control in session for use by the custom tool Session["TaskResultsControl"] = TaskResults1;
[VB]' Store the TaskResults control in session for use by the custom tool Session("TaskResultsControl") = TaskResults1 -
Add a handler for the page's PreRender event. We will add code to this handler
to initialize the resource and layer selection drop-down lists. After the
handler is added, the class should appear as follows:
[C#]public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs eventArgs) { // Store the TaskResults control in session for use by the custom tool Session["TaskResultsControl"] = TaskResults1; } protected void Page_PreRender(object sender, EventArgs eventArgs){} }
[VB]Partial Class _Default Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' Store the TaskResults control in session for use by the custom tool Session("TaskResultsControl") = TaskResults1 End Sub Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender End Sub End Class -
Now we will add code to initialize DropDownList1, which will contain the names
of the application's map resources. We implement the initialization in the
page's PreRender event because, when this event fires, the page's controls have
been loaded but have not yet been drawn. To initialize the drop-down list, we
add to it the name of each resource referred to by the application's
MapResourceManager. But before doing this, we first check whether the list
already contains items, since we only want this code to execute on application
startup.
[C#]if (DropDownList1.Items.Count == 0) { // Add resource names to the resource drop-down list foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem in MapResourceManager1.ResourceItems) DropDownList1.Items.Add(mapResourceItem.Resource.Name); }
[VB]If DropDownList1.Items.Count = 0 Then ' Add resource names to the resource drop-down list For Each mapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem _ In MapResourceManager1.ResourceItems DropDownList1.Items.Add(mapResourceItem.Resource.Name) Next End If
-
We want to initialize DropDownList2 with the names of queryable layers in the
resource currently specified by DropDownList1. The Web ADF QueryFunctionality
object's GetQueryableLayers function can be used to get an array containing
these names. This requires creating an instance of QueryFunctionality, which in
turn requires referencing a resource via the GISResource class. Note that all
of these classes are part of the Web ADF Common API, and can therefore be used
against any valid data source type.
Since we will need to get these layer names any time a new resource is selected from DropDownList1 (not just during application initialization), we will implement this logic in a separate function. Insert the following code outside the PreRender event, but inside the page class:
[C#]private string[] GetQueryableLayerNames(string resourceName) { // Get a reference to the resource ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality commonMapFunctionality = Map1.GetFunctionality(resourceName); ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = commonMapFunctionality.Resource; // Create a query functionality to use in querying the resource ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality) gisResource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null); // Get the resource's queryable layers string[] layerIDs = null; string[] layerNames = null; commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames); return layerNames; }
[VB]Private Function GetQueryableLayerNames(ByVal resourceName As String) As String() ' Get a reference to the resource Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = _ Map1.GetFunctionality(resourceName) Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = _ commonMapFunctionality.Resource ' Create a query functionality to use in querying the resource Dim commonQueryFunctionality As _ ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = _ CType(gisResource.CreateFunctionality(GetType( _ ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), _ ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality) ' Get the resource's queryable layers Dim layerIDs() As String = Nothing Dim layerNames() As String = Nothing commonQueryFunctionality.GetQueryableLayers(Nothing, layerIDs, layerNames) Return layerNames End Function
-
Now we can add a call to GetQueryableLayerNames to the PreRender event handler
and use the resulting array to initialize DropDownList2. To do this, insert the
following code in PreRender, below the DropDownList1 initialization code and
inside the if block added two steps prior.
[C#]// Get the names of queryable layers for the selected resource and add them // to the layers drop-down string[] layerNames = GetQueryableLayerNames(DropDownList1.SelectedItem.Text); for (int i = 0; i < layerNames.Length; i++) DropDownList2.Items.Add(layerNames[i]);
[VB]' Get the names of queryable layers for the selected resource and add them ' to the layers drop-down Dim layerNames() As String = GetQueryableLayerNames(DropDownList1.SelectedItem.Text) For i As Integer = 0 To layerNames.Length - 1 DropDownList2.Items.Add(layerNames(i)) Next
-
To complete our implementation of the Default page class, we need to add code
to update the drop-down list of queryable layers whenever a new resource is
selected. We can accomplish this by implementing a handler for DropDownList1's
SelectedIndexChanged event that clears the items from the layers drop-down,
gets the queryable layer names based on the item currently selected in the
resources drop-down, and add these layer names to the layers drop-down. Place
this event handler, shown below, outside the PreRender event but inside the
page class. If you are working in C#, you will also need to add a statement to
the handler for the page's Load event that explicitly adds the
SelectedIndexChanged handler. In Visual Basic, this step is unnecessary because
the event being handled is explicitly specified in the handler definition.
[C#]
Insert into Page_Load:// Add a handler for the resource drop-down's SelectedIndexChanged event DropDownList1.SelectedIndexChanged += new EventHandler(DropDownList1_SelectedIndexChanged);
Insert into the page class outside of PreRender:void DropDownList1_SelectedIndexChanged(object sender, EventArgs eventArgs) { // Clear the layers drop-down DropDownList2.Items.Clear(); // Get the names of queryable layers for the selected resource and add them // to the layers drop-down string[] layerNames = GetQueryableLayerNames(DropDownList1.SelectedItem.Text); for (int i = 0; i < layerNames.Length; i++) DropDownList2.Items.Add(layerNames[i]); }
[VB]Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged ' Clear the layers drop-down DropDownList2.Items.Clear() ' Get the names of queryable layers for the selected resource and add them ' to the layers drop-down Dim layerNames() As String = _ GetQueryableLayerNames(DropDownList1.SelectedItem.Text) For i As Integer = 0 To layerNames.Length - 1 DropDownList2.Items.Add(layerNames(i)) Next End Sub
Implementing the custom selection tool
Now that we've setup our application's user interface and implemented a way for
users to specify the selection resource and layer, we are ready to implement
our custom selection tool. This tool will use the rectangle drawn on the map by
the user of the tool to query the layer specified by the resource and layer
drop-downs, configure these results as a graphics layer, and then add them to
the TaskResults control (which will automatically add them to the Map). All
this is implemented using the Web ADF Common API – none of the data-source
specific libraries are used.
- In Solution Explorer, right-click the Web project and select "Add New Item..." In the Add New Item dialog, under the Visual Studio Installed Templates section, select the Class item. If you are using Visual C#, set the class file name to "SelectTool.cs" and make sure the selected language is Visual C#. If you are using Visual Basic, set the class file name to "SelectTool.vb" and make sure the selected language is Visual Basic. Click the Add button. Visual Studio will prompt you to create an "App_Code" folder and place the new class file inside. At this prompt, click Yes. The SelectTool.cs file should open for you to start adding content. This file will contain the code that executes when the custom selection tool is used.
-
Remove the SelectTool constructor and implement the IMapServerToolAction
interface on the SelectTool class. The code for the class should appear as
follows:
[C#]public class SelectTool : ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction { void ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction( ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs toolEventArgs) { } }
[VB]Public Class SelectTool Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction Public Sub ServerAction(ByVal toolEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs) Implements _ ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction End Sub End Class -
To start our custom tool implementation, we need to get a reference to the Map
control on which the tool was executed. The control that is the target of a
ServerAction is stored in the Control property of the arguments that are passed
to the ServerAction method, so we can get this reference from the following
code. This and the remainder of the code in the tutorial should be placed
inside the ServerAction method.
[C#]ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap = (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)toolEventArgs.Control;
[VB]Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = _ CType(toolEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)
-
Next we need the geometry of the rectangle drawn by the user. To get this, we
cast the ToolEventArgs instance passed into the ServerAction method to a
MapRectangleEventArgs object. Then we can get the reference simply by accessing
this object's MapExtent property. Note that the type of geometry referenced by
the ToolEventArgs object is determined by the ClientAction specified when the
custom tool is added to the web page. Later in the tutorial, we will specify a
ClientAction of "DragRectangle" for our custom tool, which will result in the
ToolEventArgs referencing an envelope.
[C#]ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs mapRectangleEventArgs = (ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs)toolEventArgs; ESRI.ArcGIS.ADF.Web.Geometry.Envelope adfEnvelope = mapRectangleEventArgs.MapExtent;
[VB]Dim mapRectangleEventArgs As _ ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs = CType(toolEventArgs, _ ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs) Dim adfEnvelope As ESRI.ArcGIS.ADF.Web.Geometry.Envelope = _ mapRectangleEventArgs.MapExtent
-
To select features from a resource, we need to execute a query on the resource
to get a reference to the set of features to be selected. In the Web ADF, query
functionality for a resource is exposed through a QueryFunctionality object. To
get a reference to a resource's query functionality, we need to first get a
reference to the resource via a GISResource instance. The GISResource
reference can be retrieved from the resource's MapFunctionality, which, given a
Map control and the name of the resource, can easily be retrieved via the Map's
GetFunctionality function.
Since, in this case, we already have a reference to the Map control, creating a QueryFunctionality instance depends on retrieving the name of the resource to select features from. We know the name of this resource is specified by the resource drop-down, which is an ASP.NET server control with the ID “DropDownList1.” The value of a server control is always included on postbacks in the page's NameValueCollection of request parameters with the control ID as the key. For server controls that postback synchronously (i.e. via full page postback), the value in the request parameters is only updated on synchronous postbacks. But because we've included a ScriptManager on the page and placed the drop-down in an UpdatePanel, the drop-down list posts back asynchronously. The value of an asynchronous server control is updated in the page's request parameters on both synchronous and asynchronous postbacks. Since a custom tool implementing IMapServerToolAction actually triggers an asynchronous postback (or callback if the callback framework is being used, but that doesn't apply here), we can retrieve the value of the drop-down from the page's request parameters. The code below illustrates this.
[C#]// Get the name of the resource on which to perform the selection string resourceName = (string)adfMap.Page.Request.Params["DropDownList1"]; // Get a reference to the resource ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality commonMapFunctionality = adfMap.GetFunctionality(resourceName); ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = commonMapFunctionality.Resource; // Create a query functionality to use in querying the resource ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality) gisResource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);
[VB]' Get the name of the resource on which to perform the selection Dim resourceName As String = adfMap.Page.Request.Params("DropDownList1") ' Get a reference to the resource Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = _ adfMap.GetFunctionality(resourceName) Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = _ commonMapFunctionality.Resource ' Create a query functionality to use in querying the resource Dim commonQueryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = _ CType(gisResource.CreateFunctionality(GetType( _ ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), _ ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality) -
The QueryFunctionality object's Query function requires the ID of the layer to
be queried as a parameter. We can get arrays containing the names and IDs of a
resource's queryable layers from that resource's QueryFunctionality. These
arrays are constructed such that the items at the same index of the two arrays
correspond to the same layer (e.g. the name at index 0 of the names array and
the ID at index 0 of the IDs array are the name and ID of the same layer). So,
given the name of a layer, we can determine that layer's ID by (1) determining
the index at which that layer name is stored in the names array and (2)
retrieving the ID at the same index from the IDs array. This can be done as
shown in the code below. Note that we retrieve the name of the layer to query
from the page's request parameters in the same way we retrieved the resource
name.
[C#]// Get the resource's queryable layers string[] layerIDs = null; string[] layerNames = null; commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames); // Get the name of the selection layer from the page's request parameters string selectionLayerName = (string)adfMap.Page.Request.Params["DropDownList2"]; string selectionLayerID = null; // Get the ID of the selection layer from the layer IDs array for (int i = 0; i < layerNames.Length; i++) { if (layerNames[i] == selectionLayerName) { selectionLayerID = layerIDs[i]; break; } }
[VB]' Get the resource's queryable layers Dim layerIDs() As String = Nothing Dim layerNames() As String = Nothing commonQueryFunctionality.GetQueryableLayers(Nothing, layerIDs, layerNames) ' Get the name of the selection layer from the page's request parameters Dim selectionLayerName As String = adfMap.Page.Request.Params("DropDownList2") Dim selectionLayerID As String = Nothing ' Get the ID of the selection layer from the layer IDs array For i As Integer = 0 To layerNames.Length - 1 If layerNames(i) = selectionLayerName Then selectionLayerID = layerIDs(i) Exit For End If Next -
The Query function also requires a Web ADF QueryFilter as a parameter. If, as
in this case, the query has a spatial component, then a SpatialFilter object,
which extends QueryFilter to allow specification of query geometry and other
spatial properties, should be used. Here we add code to initialize a
SpatialFilter with the user-defined envelope.
[C#]// Set-up a spatial filter to use in querying the resource ESRI.ArcGIS.ADF.Web.SpatialFilter adfSpatialFilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter(); adfSpatialFilter.ReturnADFGeometries = true; adfSpatialFilter.MaxRecords = 100; adfSpatialFilter.Geometry = adfEnvelope;
[VB]' Set-up a spatial filter to use in querying the resource Dim adfSpatialFilter As ESRI.ArcGIS.ADF.Web.SpatialFilter = _ New ESRI.ArcGIS.ADF.Web.SpatialFilter() adfSpatialFilter.ReturnADFGeometries = True adfSpatialFilter.MaxRecords = 100 adfSpatialFilter.Geometry = adfEnvelope
-
Now that we have the ID of the selection layer and a SpatialFilter that
references the user-defined selection rectangle, we can execute the query.
[C#]// Query the selection layer with the user-drawn rectangle System.Data.DataTable resultsDataTable = commonQueryFunctionality.Query( commonMapFunctionality.Name, selectionLayerID, adfSpatialFilter);
[VB]' Query the selection layer with the user-drawn rectangle Dim resultsDataTable As System.Data.DataTable = commonQueryFunctionality.Query( _ commonMapFunctionality.Name, selectionLayerID, adfSpatialFilter)
-
The Query function returns results contained in a DataTable object. While this
class provides easy access to the results data, it is not well suited to
tailoring the appearance of results. For this reason, we add code to convert
the results from a DataTable to a Web ADF GraphicsLayer.
[C#]// Convert the results data table to a graphics layer ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer resultsGraphicsLayer = ESRI.ArcGIS.ADF.Web.Converter.ToGraphicsLayer(resultsDataTable);
[VB]' Convert the results data table to a graphics layer Dim resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer = _ ESRI.ArcGIS.ADF.Web.Converter.ToGraphicsLayer(resultsDataTable)
-
Now that we have the query results as a Web ADF GraphicsLayer, we will
configure this GraphicsLayer for display in a TaskResults control. While we
could add the GraphicsLayer to the map independently of a TaskResults control,
displaying the GraphicsLayer in this way takes full advantage of the Web ADF's
attribute display and client-side rendering capabilities. First, add code to
set the selected field of each result feature to true. We do this so that the
task result node for each feature is checked, making the corresponding feature
on the map visible.
[C#]// Select each result so that its node is checked in the TaskResults control foreach (System.Data.DataRow dataRow in resultsGraphicsLayer.Rows) dataRow[resultsGraphicsLayer.IsSelectedColumn] = true;
[VB]' Select each result so that its node is checked in the TaskResults control For Each dataRow As System.Data.DataRow In resultsGraphicsLayer.Rows dataRow(resultsGraphicsLayer.IsSelectedColumn) = True Next
- Next, we retrieve the selection layer's LayerFormat and apply it
to the results GraphicsLayer. The LayerFormat object specifies a
GraphicsLayer's renderers and the format and contents of its attribute displays
(i.e. callouts and task results nodes). For feature layers, the LayerFormat
applies to results GraphicsLayers and can be specified at design time in either
Visual Studio or ArcGIS Server Manager via the Layer Properties dialog (see
Using the MapResourceManager control and Selecting layers to display).
LayerFormats can also be modified at run time programmatically (see
Working with LayerFormats). In this case, we will simply apply the
selection layer's LayerFormat to our results GraphicsLayer as-is, causing the
GraphicsLayer to appear according to the Layer Properties specified at
design-time.
[C#]// Retrieve the selection layer's layerFormat and apply it to the results ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat layerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager( adfMap.MapResourceManagerInstance, resourceName, selectionLayerID); layerFormat.Apply(resultsGraphicsLayer);
[VB]' Retrieve the selection layer's layerFormat and apply it to the results Dim layerFormat As ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat = _ ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager( _ adfMap.MapResourceManagerInstance, resourceName, selectionLayerID) layerFormat.Apply(resultsGraphicsLayer)
-
To enable functionality that relies on client-side events (e.g. mouseOver,
mouseOut, etc.), we specify that the graphics layer be rendered on the client.
This will turn on effects such as showing callouts when a result feature is
moused over and displaying a feature's highlight renderer when the
corresponding node is moused over in the TaskResults control.
[C#]// Render the results on the client to enable callouts and highlighting resultsGraphicsLayer.RenderOnClient = true;
[VB]' Render the results on the client to enable callouts and highlighting resultsGraphicsLayer.RenderOnClient = True
-
The final step in readying the GraphicsLayer for display via the TaskResults
control is placing it in a DataSet. The TaskResults control is designed to
display results contained in a DataSet, where the root node represents the
DataSet level, child nodes are created for each DataTable (i.e. GraphicsLayer)
within the DataSet, and child nodes are created on each DataTable node for each
row (i.e. feature) in each DataTable. The DataSet's name determines the text
rendered on the DataSet nodes, DataTable names determine the text rendered on
DataTable nodes, and the GraphicsLayer's LayerFormat specifies the appearance
of feature nodes. Here we give the DataSet a name that includes the
GraphicLayer's TableName, which is inherited from the name of the map layer on
which the query was executed.
[C#]// Create a DataSet and add the results to it string resultsDataSetName = string.Format("Selected Features - {0}", resultsGraphicsLayer.TableName); System.Data.DataSet resultsDataSet = new System.Data.DataSet(resultsDataSetName); resultsDataSet.Tables.Add(resultsGraphicsLayer);
[VB]' Create a DataSet and add the results to it Dim resultsDataSetName As String = String.Format("Selected Features - {0}", _ resultsGraphicsLayer.TableName) Dim resultsDataSet As System.Data.DataSet = New _ System.Data.DataSet(resultsDataSetName) resultsDataSet.Tables.Add(resultsGraphicsLayer) -
Now we are ready to add the results to the TaskResults control. This is done by
passing the results DataSet to the TaskResults' DisplayResults method. Here the
TaskResults control is retrieved from session, where it was stored in the Load
event of the Default.aspx page.
[C#]// Retrieve the TaskResults control from session and add the results to it ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults taskResults = (ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults) adfMap.Page.Session["TaskResultsControl"]; taskResults.DisplayResults(null, null, null, resultsDataSet);
[VB]' Retrieve the TaskResults control from session and add the results to it Dim taskResults As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults = _ adfMap.Page.Session("TaskResultsControl") taskResults.DisplayResults(Nothing, Nothing, Nothing, resultsDataSet) -
All that remains to complete our custom selection tool implementation is to
return the necessary callback results. When a MapServerToolAction is executed,
a callback (or partial postback) is initiated by the Map control, so that
control's callback results will automatically be processed on the client. In
this implementation, we have modified the TaskResults control, causing this
control to have callback results. So in order for the TaskResults control's
callback results to be processed on the client – and the TaskResults control
and Map to be updated accordingly – we add code to copy the TaskResults'
callback results to the Map.
[C#]// Copy the TaskResults' callback results to the Map so the results show up adfMap.CallbackResults.CopyFrom(taskResults.CallbackResults);
[VB]' Copy the TaskResults' callback results to the Map so the results show up adfMap.CallbackResults.CopyFrom(taskResults.CallbackResults)
Now that the implementation of our custom selection tool is complete, we need to add it tool to the application's Toolbar. To do this, we need to add a Tool item to the Toolbar's collection, wire the Tool to our custom tool class, specify the appropriate ClientAction, and define other properties as desired.
- Open Default.aspx in design view and select the Toolbar. In the Properties window, click the ellipsis for the ToolbarItems property. In the ToolbarItems Collection Editor dialog, add a new custom tool item by selecting “Tool” from the left-hand side of the dialog and clicking the Add button. The new Tool will appear under the Current Toolbar Contents section of the dialog.
-
Select the new Tool item in the Current Toolbar Contents section of the dialog
and examine its properties. Note that the EnablePostBack property is set to
false by default. If false, using the tool at runtime will trigger an
asynchronous callback or partial postback. If true, using the tool will trigger
a synchronous (i.e full page) postback. Since we want the tool to execute
asynchronously, keep this property set to false. Set the Tool's other
properties as follows, then click OK.
Property Value Description Text Select Tool
Label for the tool in the Toolbar ClientAction DragRectangle
Client event passed to the server Name SelectTool Object name of the tool, if used in code ServerActionAssembly App_Code
Class libraries associated with a Web site are compiled into an assembly named App_Code ServerActionClass SelectTool
The name of the custom class which implements IMapServerToolAction and will be executed when this tool is used in the map
- In design view, expand the width of the Toolbar so the text of each tool is clearly visible.
-
Run the application. Activate the custom tool by clicking “Select Tool” on the
toolbar. Use the left-most drop-down list to specify the resource to select
features from, then specify the layer to select features from using the
drop-down list on the right. Use the tool by clicking on the map and dragging
the rectangle that appears around the features you want to select. The selected
features will be highlighted according to the selection layer's LayerFormat,
and the attributes of the selected features will be displayed in the
TaskResults control.