Common Partial postback
Common_PartialPostback_CSharp\AJAXDemo.aspx.cs
// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

public partial class AJAXDemo : System.Web.UI.Page
{
    #region Instance Variable Declarations

    // Variables defining what resource, layer, and field name to use for the drop-down list and listbox
    private string m_queryResourceItemName = "MapResourceItem0";
    private string m_queryLayerName = "States";
    private string m_queryFieldName = "STATE_NAME";

    #endregion

    #region ASP.NET Page Life Cycle Event Handlers

    protected void Page_PreRender(object sender, System.EventArgs e)
    {
        string scriptKeyCustom = "customDataItemScript";
        // Check whether a script block with the name stored in scriptKeyCustom has already
        // been registered on the client, and whether the page is in an asynchronous postback.
        // If neither of these is true, create and register the script block.  Note that replacing
        // ScriptManager1.IsInAsyncPostBack with Page.IsPostback will work initially, but if a
        // full page postback occurs, the script may be lost.
        if (!this.Page.ClientScript.IsClientScriptBlockRegistered(GetType(), scriptKeyCustom) &&
        !ScriptManager1.IsInAsyncPostBack)
        {
            // Construct the JavaScript block that will be responsible for processing data items.
            // 
            // onLoadFunction specifies AsyncResponseHandler as a handler for the pageLoading AJAX
            // client-side event.  This event fires during asynchronous postbacks after the response 
            // has been received from the server, but before any content on the page is updated.  
            // 
            // AsyncResponseHandler retrieves the data items thate were registered server-side during 
            // the asynchronous postback by accessing the dataItems property on the second argument 
            // passed to the handler.  It then gets the particular data item corresponding to the 
            // page by passing the page's client ID to the dataItems array as an array index.  This 
            // data item, assumed to be formatted as a Web ADF callback result, is then passed to 
            // ESRI.ADF.System.processCallbackResult - the client-side Web ADF function responsible 
            // for parsing callback results and updating Web ADF controls accordingly.
            //
            // Below the function declarations, onLoadFunction is added as a handler for the AJAX 
            // client-side event init, which is raised one time when the page is first rendered. 
            // This is therefore the appropriate place for onLoadFunction to be called, since the 
            // asynchronous pageLoading handler in this case can remain unchanged for the life
            // of the application.
            //
            // The functions are enclosed in an extra pair of curly braces to allow the subsequent
            // call to String.Format.  String.Format is designed to replace the contents of curly
            // braces with the parameters passed to the function call.  These extra braces "escape" 
            // the braces that must enclose a JavaScript function's logic, essentially telling 
            // String.Format to not replace the contents of these particular braces.
            string scriptBlock = @"
                
                function onLoadFunction(){{
                  Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(AsyncResponseHandler);
                }}

                function AsyncResponseHandler(sender, args) {{
                  var dataItems = args.get_dataItems();
                  if (dataItems['{0}'] != null)
                    ESRI.ADF.System.processCallbackResult(dataItems['{0}']);
                }}

                Sys.Application.add_init(onLoadFunction);";

            // Insert the client ID of the page into the script block.  
            scriptBlock = string.Format(scriptBlock, Page.ClientID);

            // Register the script on the client.  This will make the script block available client-side
            // and execute statements that are not function or object declarations, in this case adding
            // onLoadFunction as a handler for the init event.
            this.Page.ClientScript.RegisterStartupScript(GetType(), scriptKeyCustom, scriptBlock, true);
        }
    }

    #endregion

    #region ASP.NET WebControl Event Handlers

    protected void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs eventArgs)
    {
        ZoomToFeatureByValue(DropDownList1.SelectedValue);
    }

    protected void ListBox1_SelectedIndexChanged(object sender, System.EventArgs eventArgs)
    {
        ZoomToFeatureByValue(ListBox1.SelectedValue);
    }
    
    #endregion

    #region Web ADF Control Event Handlers

    protected void Map1_ExtentChanged(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ExtentEventArgs args)
    {
        // New extent is the explicit envelope the Map extent will be set to.  Note that the aspect ratio of the map 
        // extent has been adjusted to account for pixel image size / extent size discrepancies. 
        ESRI.ArcGIS.ADF.Web.Geometry.Envelope adfEnvelope = args.NewExtent;

        // Get the map resource to query
        ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = 
            Map1.GetFunctionality(m_queryResourceItemName).Resource;

        // Create a Common Data Source API query functionality from 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 arrays containing the layer IDs and names of the resource's queryable layers
        string[] layerIDs = null;
        string[] layerNames = null;
        commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames);

        // Create a Web ADF spatial filter with the new map extent as the filter geometry
        ESRI.ArcGIS.ADF.Web.SpatialFilter adfSpatialFilter =
            new ESRI.ArcGIS.ADF.Web.SpatialFilter();
        adfSpatialFilter.ReturnADFGeometries = false;
        adfSpatialFilter.Geometry = adfEnvelope;

        // Loop through the layer names array until the query layer name is found.  When found, use the layer
        // ID at the current index to execute a query on the resource
        System.Data.DataTable queryResultsDataTable = null;
        for (int i = 0; i < layerNames.Length; i++)
        {
            if (layerNames[i] == m_queryLayerName)
            {
                queryResultsDataTable = commonQueryFunctionality.Query(commonQueryFunctionality.Name, 
                    layerIDs[i], adfSpatialFilter);
                break;
            }
        }

        // Populate an ArrayList with the value of the query field for each row in the query results 
        System.Collections.ArrayList arrayList = new System.Collections.ArrayList();
        foreach (System.Data.DataRow dataRow in queryResultsDataTable.Rows)
        {
            string dataRowValue = dataRow[m_queryFieldName].ToString();
            arrayList.Add(dataRowValue);
        }
        arrayList.Sort();

        ListBox1.Items.Clear();
        foreach (string item in arrayList)
        {
            // If the ScriptManager is not in an asynchronous postback, then the page is in initial load.  
            // We therefore add the current item to DropDownList1 since it has not yet been populated.
            // Otherwise, we skip this step and clear ListBox1 since that control will be re-populated with
            // the query results (i.e. features that intersect the new extent)
            if (!ScriptManager1.IsInAsyncPostBack)
                DropDownList1.Items.Add(item);

            // Add the current item to the listbox
            ListBox1.Items.Add(item);
        }
    }

    #endregion

    #region Instance Methods

    private void ZoomToFeatureByValue(string value)
    {
        // Get the resource to be queried and use it to create a Web ADF Common Data Source API
        // query functionality
        ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = 
            Map1.GetFunctionality(m_queryResourceItemName).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 arrays containing the names and IDs of the resource's queryable layers
        string[] layerIDs = null;
        string[] layerNames = null;
        commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames);

        // Create a Web ADF query filter with a where clause that will select features according
        // to the class-level field name variable and the passed-in value.  Note that the code here
        // assumes the field has a string data type.
        ESRI.ArcGIS.ADF.Web.QueryFilter adfQueryFilter = new ESRI.ArcGIS.ADF.Web.QueryFilter();
        adfQueryFilter.ReturnADFGeometries = true;
        adfQueryFilter.WhereClause = string.Format("{0} = '{1}'", m_queryFieldName, value);

        // Loop through the layer names array until the query layer name is found.  When found, use 
        // the layer ID at the current index to execute a query on the resource.
        System.Data.DataTable queryResultsDataTable = null;
        for (int i = 0; i < layerNames.Length; i++)
        {
            if (layerNames[i] == m_queryLayerName)
            {
                queryResultsDataTable = commonQueryFunctionality.Query(commonQueryFunctionality.Name, 
                    layerIDs[i], adfQueryFilter);
                break;
            }
        }

        if (queryResultsDataTable != null)
        {
            // Get the results as a Web ADF GraphicsLayer
            ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer adfGraphicsLayer =
                queryResultsDataTable as ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer;

            // Get the envelope of the geometry of the first row in the data table and use it to set 
            // the map extent.  Note that this code assumes we always want to zoom to the first row 
            // in the table.
            ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfGeometry = 
                adfGraphicsLayer.GeometryFromRow(adfGraphicsLayer.Rows[0]);
            ESRI.ArcGIS.ADF.Web.Geometry.Envelope adfEnvelope =
                ESRI.ArcGIS.ADF.Web.Geometry.Geometry.GetMinimumEnclosingEnvelope(adfGeometry).Expand(10);
            Map1.Extent = adfEnvelope;

            // Register the Map's callback results as a data item so they are processed on the client
            ScriptManager1.RegisterDataItem(Page, Map1.CallbackResults.ToString(), false);
        }
    }

    #endregion
}