Common Select Buffer tool
Common_SelectBufferTool_CSharp\App_Code\CustomControls.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.
// 

namespace CustomComponents
{
    public class ExtendToc : ESRI.ArcGIS.ADF.Web.UI.WebControls.Toc
    {
        #region Toc Members

        // Initialize the Toc's nodes to be selected on click
        protected override void OnPreRender(System.EventArgs eventArgs)
        {
            base.OnPreRender(eventArgs);

            try
            {
                // Iterate through the map's Toc functionalities
                foreach (ESRI.ArcGIS.ADF.Web.DataSources.IMapTocFunctionality tocFunctionality 
                    in this.GetFunctionalities())
                {
                    ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = tocFunctionality.Resource;

                    // Make sure the resource supports querying
                    bool resourceSupportsQuery = gisResource.SupportsFunctionality(
                        typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));
                    if (resourceSupportsQuery)
                    {
                        // Get an object to query 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);

                        // Use the query functionality to get the queryable layer names and ids from the resource
                        string[] layerIDs;
                        string[] layerNames;
                        commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames);

                        // The query functionality will not be used anymore, so remove it from the resource and
                        // dispose of it
                        gisResource.Functionalities.Remove(commonQueryFunctionality);
                        commonQueryFunctionality.Dispose();

                        // Set each node corresponding to a queryable layer to be selected when clicked
                        for (int i = 0; i < layerNames.Length; i++)
                        {
                             ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode layerNode = 
                                 Utility.FindNode(this, layerNames[i]);
                             layerNode.ClickBehavior = 
                                 ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeClickBehavior.Selectable;
                        }
                    }
                }
            }
            catch (System.Exception exception)
            {
                this.CallbackResults.Add(Utility.GetErrorCallback(exception));
            }
        }

        // Update the status bar and any associated drop-downs to display the selected layer name
        protected override void OnNodeSelect(
            ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs treeViewPlusNodeEventArgs)
        {
            try
            {
                // Fire the inherited Toc class's OnNodeSelect event
                base.OnNodeSelect(treeViewPlusNodeEventArgs);

                // Set the session variable tracking the current selection layer
                string nodeText = treeViewPlusNodeEventArgs.Node.Text;
                this.Page.Session["SelectionLayer"] = nodeText;

                // Create a JavaScript callback result to update the browser's status bar with the
                // name of the selected layer and add to the instance's callback results collection.
                // Note this only works in Internet Explorer, unless users of other browsers have
                // explicitly allowed status bar text to be set via javascript.
                string jsShowSelectionLayerOnStatusBar =
                    string.Format("window.status = 'The active selection layer is: {0}'", nodeText);
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult callbackResult =
                    ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(
                    jsShowSelectionLayerOnStatusBar);
                this.CallbackResults.Add(callbackResult);

                // Iterate through the IDs stored in NodeSelectionUpdateControls.  For each ID that refers
                // to a DropDownList, create a JavaScript callback result to update that list's text to
                // match the name of the selected layer.
                foreach (string controlID in this.NodeSelectionUpdateControls)
                {
                    System.Web.UI.Control webControl = Utility.FindControl(this.Page, controlID);
                    if (webControl is System.Web.UI.WebControls.DropDownList)
                    {
                        string jsUpdateActiveLayerDropDown = string.Format("var dropDown = " +
                            "document.getElementById('{0}');\n" +
                            "for (var i = 0; i < dropDown.options.length; i++)\n" +
                            "{{ var option = dropDown.options[i]; \n" +
                            "if (option.text == '{1}')\n" +
                            "{{ option.selected = true; }}\n" +
                            "else \n" +
                            "{{ option.selected = false; }}\n" +
                            "}}", webControl.ClientID, nodeText);
                        callbackResult =
                            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(
                            jsUpdateActiveLayerDropDown);
                        this.CallbackResults.Add(callbackResult);
                    }
                }
            }
            catch (System.Exception exception)
            {
                this.CallbackResults.Add(Utility.GetErrorCallback(exception));
            }
        }        

        // Enhance the inherited Toc's SelectedNode property by adding logic to display the passed-in
        // node as selected
        public new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode SelectedNode
        {
            get { return base.SelectedNode; }
            set
            {
                base.SelectedNode = value;

                // Fire the OnNodeSelect event to select the passed-in node
                ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs treeViewPlusNodeEventArgs =
                    new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs(value);
                OnNodeSelect(treeViewPlusNodeEventArgs);

                // Refresh the instance's HTML so that the node selection is visibly updated
                this.RefreshHtml();
            }
        }        

        #endregion

        #region Custom ExtendToc Properties

        // Stores IDs of controls to update when a node is selected
        public System.Collections.Generic.List<string> NodeSelectionUpdateControls
        {
            get
            {
                // Attempt to retrieve the ID list from state
                System.Collections.Generic.List<string> NodeSelectionUpdateControlList =
                    StateManager.GetProperty("NodeSelectionUpdateControls") as
                    System.Collections.Generic.List<string>;
                // If the list has not been stored in state, create a new list instance and place it in
                // state
                if (NodeSelectionUpdateControlList == null)
                {
                    NodeSelectionUpdateControlList = new System.Collections.Generic.List<string>();
                    StateManager.SetProperty("NodeSelectionUpdateControls", NodeSelectionUpdateControlList);
                }
                return NodeSelectionUpdateControlList;
            }
            set
            {
                // Update the ID list stored in state
                StateManager.SetProperty("NodeSelectionUpdateControls", value);
            }
        }

        #endregion

        #region Custom ExtendToc Methods

        // Function to refresh the Toc's html
        private void RefreshHtml()
        {
            try
            {
                // Instantiate an HtmlTextWriter object
                System.IO.StringWriter stringWriter = new System.IO.StringWriter();
                System.Web.UI.HtmlTextWriter htmlTextWriter = new System.Web.UI.HtmlTextWriter(stringWriter);

                // Cast the Toc to an ASP.NET web control and render its html to the HtmlTextWriter
                System.Web.UI.Control webControl = this as System.Web.UI.Control;
                webControl.RenderControl(htmlTextWriter);

                // Get the Toc's html as a string
                string htmlContent = stringWriter.ToString();

                // Close the StringWriter since we are done with it
                stringWriter.Close();

                // Instantiate and return a callback result with the control and the html.  Instantiating
                // a callback result with 3 arguments where "content" is the 2nd argument will create a
                // result instructing the out-of-the-box callback handler (ESRI.ADF.System.processCallbackResult)
                // to re-render the control specified by the 1st argument with the html contained in the 3rd
                // argument.
                this.CallbackResults.Add(ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateSetContent(
                    webControl, htmlContent));
            }
            catch (System.Exception exception)
            {
                this.CallbackResults.Add(Utility.GetErrorCallback(exception));
            }
        }

        #endregion
    }
}