Common_PostbackManager_VBNet\PostbackManager_VBNet\PostbackManager.vb
' Copyright 2011 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. ' Imports Microsoft.VisualBasic Imports System Namespace PostbackManager_VBNet #Region "PostbackManager Implementation" <AjaxControlToolkit.ClientScriptResource("PostbackManager_VBNet.PostbackManager", "PostbackManager.js")> _ Public Class PostbackManager Inherits ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl #Region "Member Variables" ' Stores the argument passed to the server during asynchronous requests Private _callbackArgument As String = Nothing ' Stores user-specified custom arguments to be passed to the client tier requestProcessed event Private _customResults As String = Nothing ' Delegate for the RequestReceived events Private Event _requestReceivedHandler As PostbackManager_VBNet.RequestReceivedEventHandler #End Region #Region "Public Properties - ExposeAdfRequestEvents, CustomResults" ''' <summary> ''' Enables event handling for requests initiated by Web ADF controls. When true, all Web ADF requests ''' will be re-routed through the PostbackManager. ''' </summary> <System.ComponentModel.Category("PostbackManager"), System.ComponentModel.DefaultValue(True), System.ComponentModel.Description("Enables event handling for requests initiated by Web ADF controls"), System.Web.UI.PersistenceMode(System.Web.UI.PersistenceMode.Attribute)> _ Public Property ExposeAdfRequestEvents() As Boolean Get If (Me.StateManager.GetProperty("ExposeAdfRequestEvents") Is Nothing) Then Return True Else Return CBool(Me.StateManager.GetProperty("ExposeAdfRequestEvents")) End If End Get Set(ByVal value As Boolean) Me.StateManager.SetProperty("ExposeAdfRequestEvents", Value) End Set End Property ''' <summary> ''' Stores properties that are returned to the client via the arguments object passed to the client tier ''' requestProcessed event. Can be used to pass data to the client without manipulating callback results. ''' </summary> <System.ComponentModel.Browsable(False)> _ Public Property CustomResults() As String Get Return _customResults End Get Set(ByVal value As String) _customResults = Value End Set End Property #End Region #Region "ASP.NET WebControl Life Cycle Event Overrides - OnPreRender, RenderContents" ' Registers script to create the client tier singleton PostbackManager instance Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs) MyBase.OnPreRender(e) ' Only execute initialization logic during full page postbacks If MyBase.IsAsync Then Return End If ' Initialize a dictionary with the properties needed to initialize the client tier ' PostbackManager singleton instance Dim clientPropertyDictionary As System.Collections.Generic.Dictionary(Of String, Object) = New System.Collections.Generic.Dictionary(Of String, Object)() clientPropertyDictionary.Add("uniqueID", Me.UniqueID) clientPropertyDictionary.Add("callbackFunctionString", Me.CallbackFunctionString) clientPropertyDictionary.Add("exposeAdfRequestEvents", Me.ExposeAdfRequestEvents) ' Serialize the properties to JSON Dim jsSerializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer() Dim clientPropertyJson As String = jsSerializer.Serialize(clientPropertyDictionary) ' Construct JavaScript to instantiate the client tier PostbackManager singleton Dim scriptKey As String = "ESRI_PostbackManager_Script" Dim initializationScript As String = "Sys.Application.add_init(function() {{" & ControlChars.CrLf & " if (ESRI.ADF.Samples.PostbackManager)" & ControlChars.CrLf & " return;" & ControlChars.CrLf & ControlChars.CrLf & " ESRI.ADF.Samples.PostbackManager = " & ControlChars.CrLf & " $create(ESRI.ADF.Samples._PostbackManager, {0}, null, null, $get('{1}'));" & ControlChars.CrLf & " }});" initializationScript = String.Format(initializationScript, clientPropertyJson, Me.ClientID) ' Register the script to execute on application startup System.Web.UI.ScriptManager.RegisterStartupScript(Me, Me.GetType(), scriptKey, initializationScript, True) End Sub ' Creates a design-time representation of the control Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter) If Me.DesignMode Then Me.RenderDesignTimeHtml(writer) Else MyBase.RenderContents(writer) End If End Sub #End Region #Region "ICallbackEventHandler Overrides - GetCallbackResult, RaiseCallbackEvent" ' Initiates callback events on the calling control, raises the RequestReceived event, ' and constructs script to invoke the client tier requestProcessed event Public Overrides Function GetCallbackResult() As String ' Parse the callback arguments into a name-value collection Dim callbackArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(_callbackArgument) Dim callingControlID As String = callbackArgs("ControlID") ' Make sure a calling control was specified in the request arguments If Not callingControlID Is Nothing Then ' Retrieve the calling control Dim callingControl As System.Web.UI.Control = PostbackManager_VBNet.PostbackManager.FindControlByClientID(Me.Page, callingControlID) ' Fire the RequestReceived event Dim requestReceivedArgs As PostbackManager_VBNet.AdfRequestEventArgs = New PostbackManager_VBNet.AdfRequestEventArgs(callingControl, _callbackArgument) Me.OnRequestReceived(requestReceivedArgs) ' Invoke ICallbackEventHandler members on the calling control if that control is not the ' PostbackManager. This also copies callback results from the calling control. If Not callingControl Is Me Then Me.DoCallerCallback(callingControl, _callbackArgument) End If ' Convert callback results into a JSON serializable object Dim jsSerializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer() Dim callbackResults As Object = Nothing If Not Me.CallbackResults.ToString() Is Nothing Then callbackResults = jsSerializer.DeserializeObject(Me.CallbackResults.ToString()) End If ' Initialize a dictionary with the results to be returned to the client tier ' requestProcessed event Dim resultsDictionary As System.Collections.Generic.Dictionary(Of String, Object) = New System.Collections.Generic.Dictionary(Of String, Object)() resultsDictionary.Add("callingControlID", callingControlID) resultsDictionary.Add("callbackResults", callbackResults) resultsDictionary.Add("customResults", Me.CustomResults) ' Serialize the results to JSON Dim resultsJson As String = jsSerializer.Serialize(resultsDictionary) ' Embed JavaScript to invoke the client tier requestProcessed event in a callback result Dim raiseRequestProcessedScript As String = String.Format("ESRI.ADF.Samples.PostbackManager._raiseEvent('requestProcessed', {0});", resultsJson) Me.CallbackResults.Add(ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(raiseRequestProcessedScript)) End If Return Me.CallbackResults.ToString() End Function ' Retrieves the argument passed to the server Public Overrides Sub RaiseCallbackEvent(ByVal eventArgument As String) MyBase.RaiseCallbackEvent(eventArgument) _callbackArgument = eventArgument End Sub #End Region #Region "IPostBackEventHandler Overrides - RaisePostBackEvent" ' Invokes web tier asynchronous request handling logic Public Overrides Sub RaisePostBackEvent(ByVal eventArgument As String) Me.RaiseCallbackEvent(eventArgument) MyBase.RaisePostBackEvent(eventArgument) End Sub #End Region #Region "Event Wiring - RequestReceived" ''' <summary> ''' Occurs when the web request has reached the server, but before the request has been processed ''' on the server by the Web ADF control initiating the request. ''' </summary> Public Custom Event RequestReceived As RequestReceivedEventHandler AddHandler(ByVal value As RequestReceivedEventHandler) AddHandler _requestReceivedHandler, value End AddHandler RemoveHandler(ByVal value As RequestReceivedEventHandler) RemoveHandler _requestReceivedHandler, value End RemoveHandler RaiseEvent(ByVal sender As Object, ByVal args As PostbackManager_VBNet.AdfRequestEventArgs) End RaiseEvent End Event ''' <summary> ''' Raises the RequestReceived event. ''' </summary> ''' <param name="args">A RequestProcessingEventArgs object that contains the Web ADF control that initiated the request.</param> Protected Overridable Sub OnRequestReceived(ByVal args As PostbackManager_VBNet.AdfRequestEventArgs) If Not _requestReceivedHandlerEvent Is Nothing Then RaiseEvent _requestReceivedHandler(Me, args) End If End Sub #End Region #Region "Private Methods" ' Calls RaiseCallbackEvent and GetCallbackResult on the passed-in control and copies callback results to ' the PostbackManager Private Sub DoCallerCallback(ByVal control As System.Web.UI.Control, ByVal callbackArgument As String) ' Check which type of Web ADF base control the passed-in control is. Then invoke the control's ' callback event methods and copy its callback results. If TypeOf control Is ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl Then Dim webControl As ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl = TryCast(control, ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl) webControl.RaiseCallbackEvent(callbackArgument) webControl.GetCallbackResult() Me.CallbackResults.CopyFrom(webControl.CallbackResults) ElseIf TypeOf control Is ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl Then Dim compositeControl As ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl = TryCast(control, ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl) compositeControl.RaiseCallbackEvent(callbackArgument) compositeControl.GetCallbackResult() Me.CallbackResults.CopyFrom(compositeControl.CallbackResults) End If End Sub ' Searches the passed-in control and all its child controls, returning that having the passed-in ' client ID, if found Private Shared Function FindControlByClientID(ByVal rootControl As System.Web.UI.Control, ByVal controlID As String) As System.Web.UI.Control ' Return the passed-in control if it has the passed-in ID If rootControl.ClientID = controlID Then Return rootControl End If ' Iterate through the control's child controls, recursively calling FindControl on each. ' If at any point a control with the passed-in ID is found, return it. For Each childControl As System.Web.UI.Control In rootControl.Controls Dim foundControl As System.Web.UI.Control = FindControlByClientID(childControl, controlID) If Not foundControl Is Nothing Then Return foundControl End If Next childControl Return Nothing End Function ' Renders the control at design-time Private Sub RenderDesignTimeHtml(ByVal writer As System.Web.UI.HtmlTextWriter) ' Create a table to format the design-time display Dim table As System.Web.UI.WebControls.Table = New System.Web.UI.WebControls.Table() table.Font.Name = Me.Font.Name table.Font.Size = Me.Font.Size table.Style(System.Web.UI.HtmlTextWriterStyle.BackgroundColor) = "white" table.BorderColor = System.Drawing.Color.Black table.BorderStyle = System.Web.UI.WebControls.BorderStyle.Solid table.BorderWidth = 1 Dim row As System.Web.UI.WebControls.TableRow = New System.Web.UI.WebControls.TableRow() table.CellPadding = 4 table.Rows.Add(row) ' Add the control's ID Dim cell As System.Web.UI.WebControls.TableCell = New System.Web.UI.WebControls.TableCell() row.Cells.Add(cell) cell.Style(System.Web.UI.HtmlTextWriterStyle.WhiteSpace) = "nowrap" cell.Text = String.Format("{0}<br>", Me.ClientID) row = New System.Web.UI.WebControls.TableRow() table.Rows.Add(row) ' Add the control type cell = New System.Web.UI.WebControls.TableCell() row.Cells.Add(cell) cell.Text = "PostbackManager WebControl" table.RenderControl(writer) End Sub #End Region End Class #End Region #Region "Event Delegate and Argument Classes - RequestReceivedEventHandler, AdfRequestEventArgs" ''' <summary>Delegate to handle the RequestReceived event.</summary> ''' <param name="sender">The PostbackManager Control that initiated the event.</param> ''' <param name="args">Arguments that include the ADF Control that initiated the request.</param> Public Delegate Sub RequestReceivedEventHandler(ByVal sender As Object, ByVal args As PostbackManager_VBNet.AdfRequestEventArgs) ''' <summary>Event arguments for a Web ADF asyncrhonous request.</summary> Public Class AdfRequestEventArgs Inherits System.EventArgs Private _callingControl As System.Web.UI.Control Private _requestArguments As String ''' <summary>Constructor.</summary> ''' <param name="callingControl">The Web ADF control that initiated the request.</param> ''' <param name="requestArguments">The arguments passed to the server in the request.</param> Public Sub New(ByVal callingControl As System.Web.UI.Control, ByVal requestArguments As String) _callingControl = callingControl _requestArguments = requestArguments End Sub ''' <summary>The Web ADF control that initiated the request.</summary> Public ReadOnly Property CallingControl() As System.Web.UI.Control Get Return _callingControl End Get End Property ''' <summary>The arguments passed along with the request.</summary> Public ReadOnly Property RequestArguments() As String Get Return _requestArguments End Get End Property End Class #End Region End Namespace