Common Custom tasks
Common_CustomTasks_CSharp\OptimizeTask_CSharp\OptimizeTask.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 OptimizeTask_CSharp
{
    // Specifies the default markup inserted when the task is dragged from the toolbox onto a
    // page in Visual Studio
    [System.Web.UI.ToolboxData("<{0}:OptimizeTask_CSharp runat=\"server\" Width=\"100px\" BorderWidth=\"1px\"><TaskResultsContainers><esri:BuddyControl Name=\"TaskResults1\" /></TaskResultsContainers> </{0}:OptimizeTask_CSharp>")]
    public class OptimizeTask : ESRI.ArcGIS.ADF.Web.UI.WebControls.FloatingPanelTask
    {
        #region Instance Variable Declarations

        private CustomCallbackButton _handleCallbackButton;
        private System.Web.UI.WebControls.Button _handlePartialPostBackButton;
        private ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults _taskResults;
        private string m_taskTextKey = "textValue";

        #endregion

        #region Instance Properties

        public string ButtonText
        {
            get
            {
                // Attempt to retrieve the button text from state
                object buttonTextObject = StateManager.GetProperty("buttonText");
                // If no button text was stored in state, return the default value.  Otherwise,
                // return the text as a string.
                return (buttonTextObject == null) ? "Execute" : buttonTextObject as string;
            }
            set
            {
                // Store the passed-in value in state
                StateManager.SetProperty("buttonText", value);
            }
        }

        // Convenient access to the first TaskResults control in the Task's TaskResultsContainers collection
        internal ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults TaskResultsInstance
        {
            get
            {
                // Retrieve the TaskResults control if it has not already been
                if ((_taskResults == null) && (this.TaskResultsContainers[0] != null))
                    _taskResults = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl(
                        this.TaskResultsContainers[0].Name, this.Page)
                        as ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults;

                return _taskResults;
            }
        }

        #endregion
        
        // Configures the task's interface - NOTE: AsyncOptimizer is used in this method 
        protected override void CreateChildControls()
        {
            Controls.Clear();
            base.CreateChildControls();

            // Determine calling control if an async request.  
            // If not this task or child component within this task, skip creating
            // child controls.
            AsyncOptimizer asyncOptimizer = new AsyncOptimizer(this);
            if (!asyncOptimizer.RequiresChildControls)
                return;

            // Clear list of task child controls that make async calls (readd controls if necessary below) 
            asyncOptimizer.ChildControlsHandlingAsyncCalls.Clear();

            // If there is no ScriptManager on the page, initialize and add custom callback button to the task.
            // Otherwise, add a partial postback button.  Both controls will initiate an async request that 
            // does not execute the task, but is processed by an event on the control.  As a result,
            // task content must be recreated to process the request.    
            if (this.ScriptManager == null)
            {
                #region Custom Callback Button Instantiation

                // Initialize a custom callback button and add it to the task's controls collection
                _handleCallbackButton = new CustomCallbackButton();
                _handleCallbackButton.ID = "CallbackButton";
                _handleCallbackButton.Text = "Handle Callback";
                _handleCallbackButton.UseSubmitBehavior = false;
                _handleCallbackButton.TaskInstance = this;

                Controls.Add(_handleCallbackButton);
                #endregion

                // Register this control with the AsyncOptimizer as a control that may initiate an async request.
                // If it does, CreateChildControls in this task will execute normally.  Note, the list of control ids
                // is stored in session.
                asyncOptimizer.ChildControlsHandlingAsyncCalls.Add(_handleCallbackButton.UniqueID);
            }
            else
            {
                #region Partial PostBack Button Instantiation

                // Initialize a button that will trigger a partial postback
                _handlePartialPostBackButton = new System.Web.UI.WebControls.Button();
                _handlePartialPostBackButton.ID = "partialPostBackButton";
                _handlePartialPostBackButton.Text = "Handle Partial PostBack";
                //_handlePartialPostBackButton.UseSubmitBehavior = false;

                // Wire a handler for the button's click event
                _handlePartialPostBackButton.Click += new System.EventHandler(HandlePartialPostBackButton_Click);

                // Regiester the button as an asyncrhonous postback control so it triggers a partial postback
                // when clicked
                ScriptManager.RegisterAsyncPostBackControl(_handlePartialPostBackButton);

                // Add the button to the task's controls collection
                Controls.Add(_handlePartialPostBackButton);

                #endregion

                // Register this control with the AsyncOptimizer as a control that may initiate an async request.
                // If it does, CreateChildControls in this task will execute normally.  Note, the list of control ids
                // is stored in session.
                asyncOptimizer.ChildControlsHandlingAsyncCalls.Add(_handlePartialPostBackButton.UniqueID);

            }

            #region Textbox containing value to pass during task execution
            // Create a textbox and add it to the task's controls collection
            System.Web.UI.WebControls.TextBox textBox = new System.Web.UI.WebControls.TextBox();
            textBox.ID = "PostBackTaskTextBox";
            Controls.Add(textBox);

            // Define an argument to return when executing the task
            string customArguments = string.Format("'{0}=' + ESRI.ADF.System.escapeForCallback($get('{1}').value)", m_taskTextKey,textBox.ClientID);
            #endregion

            #region Button Initiating Task Execution via Web ADF Task Framework

            // Create a button for task execution
            System.Web.UI.WebControls.Button executeTaskButton = new System.Web.UI.WebControls.Button();
            executeTaskButton.Text = "Execute Task";

            // Construct JavaScript that calls the Web ADF's executeTask function.  This will initiate
            // a callback that invokes the task's ExecuteTask method on the server.
            string executeTaskJavaScript = string.Format("ESRI.ADF.Tasks.executeTask({0}, \"{1}\");return false;",
                customArguments, CallbackFunctionString);

            // Wire the JavaScript to execute when the button is clicked
            executeTaskButton.OnClientClick = executeTaskJavaScript;

            // Add the button to the task's controls colleciton
            Controls.Add(executeTaskButton);

            
            #endregion
        }

        protected override void OnPreRender(System.EventArgs e)
        {
            base.OnPreRender(e);
            #region Partial PostBack Response Handling

            // Create the JavaScript necessary to pass the result of a partial postback to the Web ADF
            // JavaScript library's processCallbackResult function
            string scriptKeyCustom = "customDataItemScript";
            if (!this.Page.ClientScript.IsStartupScriptRegistered(GetType(), scriptKeyCustom) && this.ScriptManager != null)
            {
                string processDataItemJavaScript = @"
                
                        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);";
                processDataItemJavaScript = string.Format(processDataItemJavaScript, this.Page.ClientID);

                // Register the script as a startup script so the result handling code is wired during
                // applicaton initialization
                this.Page.ClientScript.RegisterStartupScript(GetType(), scriptKeyCustom,
                    processDataItemJavaScript, true);

            }

            #endregion

        }


        #region Task Overrides

        // Fires first when the task is executed.  Retrieves the values needed to perform the necessary
        // server-side action.
        public override string GetCallbackResult()
        {
            // Set the task's Input member to the value of the task's textbox 
            System.Collections.Specialized.NameValueCollection keyValColl =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(
                CallbackEventArgument);
            Input = keyValColl[m_taskTextKey];
            return base.GetCallbackResult();
        }

        // Fires second when the task is executed.  Performs the necessary server-side logic.
        public override void ExecuteTask()
        {
            // Clear any left-over task results and make sure task input exists
            Results = null;
            if (Input == null) return;

            // Get the task's textbox value from the Input property
            string textBoxValue = Input as string;

            // Format the heading of the task result to display the current time on the server
            string taskResultHeading = string.Format("The time on the server is {0}",
                System.DateTime.Now.ToShortTimeString());

            // Format the detail of the task result to display the value of the task's textbox when
            // the task was executed
            string taskResultDetail = string.Format("The value in the text box is: {0}", textBoxValue);

            // Create a simple task result with the heading and detail
            ESRI.ArcGIS.ADF.Web.UI.WebControls.SimpleTaskResult simpleTaskResult =
                new ESRI.ArcGIS.ADF.Web.UI.WebControls.SimpleTaskResult(taskResultHeading, taskResultDetail);

            // Set the task's Results property to the simple task result.  The contents of this property
            // will be passed to the task's results container.
            Results = simpleTaskResult;

        }

        // Overriden to return an empty list, indicating that the task has no resource dependencies.
        public override System.Collections.Generic.List<
            ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency> GetGISResourceItemDependencies()
        {
            System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency>
                list = new System.Collections.Generic.List<
                ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency>();
            return list;
        }

        #endregion

        #region UI Event Handlers - HandlePartialPostBackButton_Click

        // Fires when the Handle Partial PostBack button is clicked
        void HandlePartialPostBackButton_Click(object sender, System.EventArgs e)
        {
            // Zoom the map
            if (TaskResultsInstance.MapInstance != null)
                TaskResultsInstance.MapInstance.Zoom(2);

            // Copy the map's callback results to the task results container's callback results collection
            TaskResultsInstance.CallbackResults.CopyFrom(TaskResultsInstance.MapInstance.CallbackResults);

            // Register the task results container's callback results as a data item.  This will pass the
            // callback results to the client-side AsyncResponseHandler function that was registered in
            // OnPreRender.  This function, in turn, will pass the callback results to the Web ADF's 
            // processCallbackResults function.
            this.ScriptManager.RegisterDataItem(Page, TaskResultsInstance.CallbackResults.ToString(), false);
        }

        #endregion
    }

    public class CustomCallbackButton : System.Web.UI.WebControls.Button, System.Web.UI.ICallbackEventHandler
    {
        #region Instance Variable Declarations

        private string _callbackArg;
        private OptimizeTask _task;

        #endregion

        protected override void OnPreRender(System.EventArgs e)
        {
            base.OnPreRender(e);

            #region Custom Callback Button Click Handling

            // Get the JavaScript syntax for invoking a callback to the callback button
            string callbackInvocationString = Page.ClientScript.GetCallbackEventReference(
                this, "argument", "processCallbackResult", "context");

            // Construct JavaScript to create an argument string containing the browser's dimensions
            // and execute a callback to pass the argument to the server.
            string callbackJavaScript = @"
                        var argument = 'callbackArgument=ZoomMap';
                        var context = null;
                        {0};
                        return;
                    ";
            // Substitute the callback invocation into the callback packaging JavaScript
            callbackJavaScript = string.Format(callbackJavaScript, callbackInvocationString);

            // Wire the script to the callback button's click event
            OnClientClick = callbackJavaScript;

            #endregion
        }


        #region ICallbackEventHandler Members - RaiseCallbackEvent, GetCallbackResult

        // The first method to execute on the server when a callback is invoked from the client.  The string
        // containing the callback's parameters is passed to this method.
        public void RaiseCallbackEvent(string eventArgument)
        {
            // Store the callback argument string in an instance variable for reference in GetCallbackResult
            _callbackArg = eventArgument;
        }

        // Fires when a callback string referencing a CustomCallbackButton instance is invoked from the client.  
        // In the PostBackTask implementation above, the JavaScript needed to do that is wired to a 
        // CustomCallbackButton instance in the OnPreRender method.
        public string GetCallbackResult()
        {
            // Use the Web ADF's callback parsing utility to split the callback argument string into a 
            // collection of name-value pairs.
            System.Collections.Specialized.NameValueCollection callbackArgsCollection =
                ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(
                _callbackArg);

            // Get the callback argument from the collection
            string callbackArguments = callbackArgsCollection["callbackArgument"];

            if (!string.IsNullOrEmpty(callbackArguments))
            {
                if (callbackArguments == "ZoomMap")
                {
                    // Zoom the map buddied to the callback button's parent PostBackTask
                    if (this.TaskInstance.TaskResultsInstance.MapInstance != null)
                        this.TaskInstance.TaskResultsInstance.MapInstance.Zoom(2);

                    // Copy the map's callback results to the task results container's results collection
                    this.TaskInstance.TaskResultsInstance.CallbackResults.CopyFrom(
                         this.TaskInstance.TaskResultsInstance.MapInstance.CallbackResults);
                }
            }

            return TaskInstance.TaskResultsInstance.CallbackResults.ToString();
        }

        #endregion

        #region Instance Properties - PostBackTaskInstance

        // Provides access to the parent task
        internal OptimizeTask TaskInstance
        {
            get { return _task; }
            set { _task = value; }
        }

        #endregion
    }
}