Using the common data source API in a Web application


In this topic


About using the common data source API

Through the common data source application programming interface (API), the Web Application Developer Framework (ADF) provides endpoints to retrieve and manipulate 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.
This topic shows how to query resources and create graphics showing query results using only the common API. Step-by-step instructions are provided to create a Web ADF application in Visual Studio 2008 that contains a custom selection tool. This tool uses classes from the common API to retrieve feature data from a user-defined resource and layer, and spatially shows this data as a Web ADF GraphicsLayer.
Attributes for these features show on a Web ADF TaskResults control and in callouts (that is, MapTips) that appear when the cursor hovers over a feature on the map. This topic also demonstrates the use of ASP.NET Asynchronous JavaScript and XML (AJAX) functionality to dynamically update Web controls via partial postback. The MapResourceManager, Map, Toc, Toolbar, and TaskResults Web ADF controls are used in this topic.

Designing a Web application

This Web application consists of a subset of Web ADF controls that provide basic geographic information system (GIS) functionality and several other controls (Web ADF and non-Web ADF) used in conjunction with your custom selection tool implementation.
The basic controls include a Map control to display GIS data, a Toc control to allow toggling of map layer visibility, a Toolbar control to enable interaction with the map, and a MapResourceManager control to provide the Web ADF controls access to map services.
You will also add a Web ADF TaskResults control to display the attributes of features selected with your custom tool, and two ASP.NET DropDownLists to enable run time specification of the resource and layer from which to select features. You will embed the DropDownLists in an ASP.NET AJAX UpdatePanel to allow asynchronous updating of these controls via partial postback and include an ASP.NET AJAX ScriptManager to support asynchronous functionality.
  1. Create a Web application using the steps in How to create a Web application with Web controls
  2. In design view, drag a ScriptManager control from the AJAX Extensions section on the Toolbox panel in Visual Studio. Drop the control in the top left corner on the Default.aspx page above the Map and MapResourceManager controls. For ASP.NET AJAX functionality to work, the ScriptManager must be located on the page before any controls that use AJAX functionality.
  3. Drag and drop a Web ADF TaskResults control onto the page. Use this control to show the attributes of selected features.
  4. Position the TaskResults control below the Toc control. Make the control absolutely positioned by using the Position dialog box (Select the control -->Go to Format Menu--> click option position--> From the position dialog box select Absolute and hit OK to apply). Drag the control until it is positioned below the Toc control. Expand the width of the control to at least 300 pixels wide.
  5. Set the TaskResults control's BuddyControl property. Select the TaskResults control in design view or on the Properties window. Click the drop-down list for the BuddyControl property. The list includes the names of available Map controls on the page. Select the name of the previously added Map control (by default, Map1).
  6. From the AJAX Extensions section on the Visual Studio Toolbox panel, drag an UpdatePanel onto the page and drop it below the toolbar. Use this to enable AJAX functionality for the two drop-down lists that specify the resource and layer from which to select features.
  7. Drag a DropDownList control from the Standard section on the Visual Studio toolbox, then drop it in the UpdatePanel. On the menu that appears, select Enable AutoPostBack to make the DropDownList issue a postback when a new item is selected at run time. Because you are placing the control within an UpdatePanel, the postback is an asynchronous partial postback, rather than a full page postback. The DropDownList is used to specify the map resource from which to select features.
  8. Drag and drop another DropDownList into the UpdatePanel and enable AutoPostBack for this list. Use this control to specify the layer from which to select features. In design view, the application appears as shown in the following screen shot:

Implementing page and control event handlers

To configure your application's user interface (UI), two DropDownList controls were added allowing users to specify the resource and layer from which to select features, and a TaskResults control to display the attributes of selected features.
The DropDownLists will not contain any items out-of-the-box; therefore, explicitly initialize them with the names of the application's resources and layers. You also want the layers list to dynamically update when a new resource is selected (requires some code). Since you want the TaskResults control to display your custom tool's results, give your custom tool access to it. Implement logic to handle all of these requirements on the default page's code-behind class.
  1. In the Solution Explorer, expand Default.aspx and double-click Default.aspx.cs (if you are using C#) or Default.aspx.vb (if you are using Visual Basic) to open the default code-behind class.
  2. Add the results from your custom selection tool to the application's TaskResults control. Get a reference to the TaskResults control from within the custom tool's implementation. While there are a number of ways to do this, for simplicity, use session storage. Store a reference to the control in session by adding the following code example to the handler for the page's Load event. 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.NET]
' Store the TaskResults control in session for use by the custom tool.
Session("TaskResultsControl") = TaskResults1
  1. Add a handler for the page's PreRender event. Add code to this handler to initialize the resource and layer selection drop-down lists. After the handler is added, the class appears as shown in the following code example:
[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.NET]
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
  1. Add code to initialize DropDownList1, which contains the names of the application's map resources. Implement the initialization in the page's PreRender event because when this event fires, the page's controls are loaded but not drawn. To initialize the drop-down list, add to it the name of each resource referred to by the application's MapResourceManager. However, before doing this, verify that the list contains items, since you only want this code to execute at application startup. See the following code example:
[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.NET]
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
  1. 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 requires referencing a resource via the GISResource class. All of these classes are part of the Web ADF common API and can be used against any valid data source type.

    Since you need to get these layer names when a new resource is selected from DropDownList1 (not just during application initialization), implement this logic in a separate function. Insert the following code example outside the PreRender event and 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.NET]
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
  1. Add a call to GetQueryableLayerNames to the PreRender event handler and use the resulting array to initialize DropDownList2. Insert the following code example in PreRender below the DropDownList1 initialization code and inside the previously added if block.
[C#]
// Get the names of queryable layers for the selected resource and add them
// to the layers' drop-down list.
string[] layerNames = GetQueryableLayerNames(DropDownList1.SelectedItem.Text);
for (int i = 0; i < layerNames.Length; i++)
    DropDownList2.Items.Add(layerNames[i]);
[VB.NET]
' Get the names of queryable layers for the selected resource and add them
' to the layers' drop-down list.
Dim layerNames() As String = GetQueryableLayerNames(DropDownList1.SelectedItem.Text)
For i As Integer = 0 To layerNames.Length - 1
    DropDownList2.Items.Add(layerNames(i))
Next
  1. To complete the implementation for the default page class, add code to update the drop-down list of queryable layers when a new resource is selected.
    1. Implement a handler for the DropDownList1's SelectedIndexChanged event that clears the items from the layers' drop-down list, gets the queryable layer names based on the item selected in the resources' drop-down list, then add these layer names to the layers' drop-down list.
    2. Place this event handler outside the PreRender event and inside the page class. If you are using C#, add a statement to the handler for the page's Load event that explicitly adds the SelectedIndexChanged handler.

      In Visual Basic, this step is not required because the event being handled is explicitly specified in the handler definition.

      For C#, insert the following code example into Page_Load:
[C#]
// Add a handler for the resource drop-down list's SelectedIndexChanged event.
DropDownList1.SelectedIndexChanged += new EventHandler
    (DropDownList1_SelectedIndexChanged);
    Insert the following code example into the page class outside of PreRender:
[C#]
void DropDownList1_SelectedIndexChanged(object sender, EventArgs eventArgs)
{
    // Clear the layers' drop-down list.
    DropDownList2.Items.Clear();
    // Get the names of queryable layers for the selected resource and add them
    // to the layers' drop-down list.
    string[] layerNames = GetQueryableLayerNames(DropDownList1.SelectedItem.Text);
    for (int i = 0; i < layerNames.Length; i++)
        DropDownList2.Items.Add(layerNames[i]);
}
[VB.NET]
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, _
                                                 ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
' Clear the layers' drop-down list.
DropDownList2.Items.Clear()
' Get the names of queryable layers for the selected resource and add them
' to the layers' drop-down list.
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 a custom selection tool

Now that you have set up your application's UI and implemented a method to specify the selection resource and layer, implement your custom selection tool. This tool uses the rectangle drawn on the map by the user of the tool to query the layer specified by the resource and layer drop-down lists. Configure these results as a graphics layer and add them to the TaskResults control (which automatically adds them to the Map). All of this is implemented using the Web ADF common API—none of the data source specific libraries are used.
  1. In the Solution Explorer, right-click the Web project and select Add New Item. The Add New Item dialog box appears.
  2. On the Add New Item dialog box, 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.
  3. Click the Add button. Visual Studio prompts you to create an App_Code folder and place the new class file inside.
  4. Click Yes. The SelectTool.cs file opens for you to start adding content. This file contains the code that executes when the custom selection tool is used.
  5. Remove the SelectTool constructor and implement the IMapServerToolAction interface on the SelectTool class. See the following code example that shows the code for the class:
[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.NET]
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
  1. To start your custom tool implementation, 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 passed to the ServerAction method; therefore, you can get this reference from the following code example. Place this and the remainder of the code in this topic inside the ServerAction method.
[C#]
ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap = 
    (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)toolEventArgs.Control;
[VB.NET]
Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = _
                                                       CType(toolEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)
  1. You need the geometry of the rectangle drawn by the user. To get this, cast the ToolEventArgs instance passed into the ServerAction method to a MapRectangleEventArgs object. Get the reference by accessing this object's MapExtent property. The type of geometry referenced by the ToolEventArgs object is determined by the specified ClientAction when the custom tool is added to the Web page. In the Adding a custom tool to an application section in this topic, you will specify a ClientAction of DragRectangle for your custom tool, which results in the ToolEventArgs referencing an envelope. See the following code example:
[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.NET]
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
  1. To select features from a resource, 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, 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 be retrieved via the Map's GetFunctionality function.

    Since you already have a reference to the Map control, creating a QueryFunctionality instance depends on retrieving the name of the resource from which to select features. You know the name of this resource is specified by the resource's drop-down list, which is an ASP.NET server control with the DropDownList1 ID. 

    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 (that is, via full page postback), the value in the request parameters is only updated on synchronous postbacks. However, because you have included a ScriptManager on the page and placed the drop-down list 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 synchronous and asynchronous postbacks. Since a custom tool implementing IMapServerToolAction triggers an asynchronous postback (or callback if the callback framework is used; however, this does not apply here), you can retrieve the value of the drop-down list from the page's request parameters. See the following code example that shows 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.NET]
' 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)
  1. The QueryFunctionality object's Query function requires the ID of the layer to be queried as a parameter. Get arrays containing the names and IDs of a resource's queryable layers from that resource's QueryFunctionality. These arrays are constructed so the items at the same index of the two arrays correspond to the same layer (for example, 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).

    Given the name of a layer, you can determine that layer's ID by determining the index at which that layer name is stored in the names' array and retrieving the ID at the same index from the IDs' array. This can be done as shown in the following code example. The layer's name is retrieved form the page's request parameter by the same method in which you 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.NET]
' 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
  1. The Query function also requires a Web ADF QueryFilter as a parameter. If, as in this case, the query has a spatial component, use a SpatialFilter object, which extends QueryFilter to allow specification of query geometry and other spatial properties. The following code example shows initializing 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.NET]
' 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
  1. Now that you have the ID of the selection layer and a SpatialFilter that references the user-defined selection rectangle, execute the query. See the following code example:
[C#]
// Query the selection layer with the user drawn rectangle.
System.Data.DataTable resultsDataTable = commonQueryFunctionality.Query
    (commonMapFunctionality.Name, selectionLayerID, adfSpatialFilter);
[VB.NET]
' Query the selection layer with the user drawn rectangle.
Dim resultsDataTable As System.Data.DataTable = commonQueryFunctionality.Query( _
                                                commonMapFunctionality.Name, selectionLayerID, adfSpatialFilter)
  1. The Query function returns results contained in a DataTable object. While this class provides easy access to the results data, it is not beneficial when customizing the results' appearance. For this reason, add code to convert the results from a DataTable to a Web ADF GraphicsLayer. See the following code example:
[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.NET]
' 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)
  1. Now that you have the query results as a Web ADF GraphicsLayer, configure this GraphicsLayer to display in a TaskResults control. While you can add the GraphicsLayer to the map independently of a TaskResults control, displaying the GraphicsLayer this way takes advantage of the Web ADF's attribute display and client-side rendering capabilities.

    Add code to set the selected field of each result feature to true. Do this so the task result node for each feature is selected, making the corresponding feature on the map visible. See the following code example:
[C#]
// Choose each result so that its node is selected in the TaskResults control.
foreach (System.Data.DataRow dataRow in resultsGraphicsLayer.Rows)
    dataRow[resultsGraphicsLayer.IsSelectedColumn] = true;
[VB.NET]
' Choose each result so that its node is selected in the TaskResults control.
For Each dataRow As System.Data.DataRow In resultsGraphicsLayer.Rows
    dataRow(resultsGraphicsLayer.IsSelectedColumn) = True
Next
  1. 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 display (that is, callouts and task results nodes). For feature layers, the LayerFormat applies to the results GraphicsLayer's and can be specified at design time in Visual Studio or ArcGIS Server Manager via the Layer Properties dialog box. For more information, see How to use the MapResourceManager control and Selecting layers to display).

    LayerFormats can also be modified programmatically at run time. For more information, see Working with layer formats. In this case, apply the selection layer's LayerFormat to your results GraphicsLayer as it currently exists, causing the GraphicsLayer to appear according to the Layer Properties specified at design time. See the following code example:
[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.NET]
' 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)
  1. To enable functionality that relies on client-side events (for example, mouseOver, mouseOut, and so on), specify that the graphics layer be rendered on the client. This turns on effects, such as showing callouts when the cursor hovers over a result feature and displays a feature's highlight renderer when the cursor hovers over a corresponding node in the TaskResults control. See the following code example:
[C#]
// Render the results on the client to enable callouts and highlighting.
resultsGraphicsLayer.RenderOnClient = true;
[VB.NET]
' Render the results on the client to enable callouts and highlighting.
resultsGraphicsLayer.RenderOnClient = True
  1. The final step to ready the GraphicsLayer for display via the TaskResults control is placing it in a DataSet. The TaskResults control displays results contained in a DataSet, where the root node represents the DataSet level, child nodes are created for each DataTable (that is, GraphicsLayer) within the DataSet, and child nodes are created on each DataTable node for each row (that is, 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. Give the DataSet a name that includes the GraphicLayer's TableName, which is inherited from the map layer's name on which the query was executed. See the following code example:
[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.NET]
' 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)
  1. Add the results to the TaskResults control by passing the results DataSet to the TaskResults' DisplayResults method. The TaskResults control is retrieved from session, where it was stored in the Load event on the Default.aspx page. See the following code example:
[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.NET]
' 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)
  1. To complete your custom selection tool implementation, 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 is automatically processed on the client. In this implementation, you have modified the TaskResults control, causing this control to have callback results. For the TaskResults control's callback results to be processed on the client—and the TaskResults control and Map to update accordingly—add code to copy the TaskResults' callback results to the Map. See the following code example:
[C#]
// Copy the TaskResults' callback results to the Map so the results appear.
adfMap.CallbackResults.CopyFrom(taskResults.CallbackResults);
[VB.NET]
' Copy the TaskResults' callback results to the Map so the results appear.
adfMap.CallbackResults.CopyFrom(taskResults.CallbackResults)

Adding a custom tool to an application

Now that the implementation of your custom selection tool is complete, add it to the application's toolbar. To do this, add a tool item to the toolbar's collection, wire the tool to your custom tool class, specify the appropriate ClientAction, and define other properties as necessary.
  1. Open the Default.aspx page in design view and select the toolbar. On the Properties window, click the ellipsis button for the ToolbarItems property. The ToolbarItems Collection Editor dialog box appears.
  2. On the ToolbarItems Collection Editor dialog box, add a new custom tool item by selecting Tool on the left side of the dialog box, then click Add. The new tool appears under the Current Toolbar Contents section on the dialog box. 
  3. Select the new tool item on the Current Toolbar Contents section on the dialog box and examine its properties. By default, the EnablePostBack property is set to false. If set to false, using the tool at runtime triggers an asynchronous callback or partial postback. If set to true, using the tool triggers a synchronous (that is, full page) postback. Since you want the tool to execute asynchronously, keep this property set to false.
  4. Set the tool's other properties as shown in the following table, then click OK.
Property
Value
Description
Text
SelectTool
Tool's label on the toolbar.
ClientAction
DragRectangle
Client event passed to the server.
Name
SelectTool
Tool's object name if used in code.
ServerActionAssembly
App_Code
Class libraries associated with a Web site are compiled into an assembly named App_Code.
ServerActionClass
SelectTool
Name of the custom class that implements IMapServerToolAction and executes when this tool is used on the map.
  1. In design view, expand the width of the toolbar so the text of each tool is clearly visible.
  2. Run the application. Click Select Tool on the toolbar to activate the custom tool.
  3. Click the left-most drop-down list to specify the resource from which to select features, then specify the layer from which to select features using the drop-down list on the right.
  4. Click the map to use the tool and drag the rectangle that shows around the features you want to select. The selected features are highlighted according to the selection layer's LayerFormat and the attributes of the selected features show on the TaskResults control.

    See the following screen shot that shows the custom selection tool Web application at run time:

     


See Also:

How to create a Web application with Web controls
MapResourceManager control
Working with the MapResourceManager control
Selecting layers to display
Working with layer formats