Quantcast
Channel: Development With A Dot
Viewing all articles
Browse latest Browse all 404

ASP.NET Callback Panel

$
0
0

Continuing with my quest for reusable, no dependencies, Web Forms AJAX controls, this time I wanted a replacement for the venerable UpdatePanel control. Specifically, I wanted to address the following issues:

  • Allow the partial update of a region on my page, including all of its controls;
  • Being able to cause an update through JavaScript (tricky with UpdatePanel);
  • Have the ability to only send data for controls living inside my control, not everything else on the page (read, __VIEWSTATE);
  • Support JavaScript events at the beginning/end of a callback or in the occurrence of an error (yes, I know about PageRequestManager, but I wanted something different).

I ended up with a CallbackPanel control, which is what I am going to talk about. Here is its declaration:

   1:<web:CallbackPanelrunat="server"ID="callback"SendAllData="false"OnBeforeCallback="onBeforeCallback"OnAfterCallback="onAfterCallback"OnCallbackError="onCallbackError"OnCallback="OnCallback">
   2:<!-- some controls -->
   3:<asp:Labelrunat="server"ID="time"/>
   4:<asp:TextBoxrunat="server"ID="text"/>
   5:<asp:Buttonrunat="server"ID="button"Text="Button"/>
   6:</web:CallbackPanel>

The CallbackPanel control supports some properties:

  • SendAllData: if all the data in the form should be sent, including viewstate, or just the data for the controls inside the CallbackPanel (default is false);
  • OnAfterCallback: the name of a JavaScript function to be called after the callback terminates;
    OnBeforeCallback: the optional name of a JavaScript function that gets called before a callback; if we so want, we can return false on this function to cancel the callback;
  • OnCallbackError: the name of a JavaScript function that is called in the event of an error.

Some examples of the JavaScript functions:

   1:<scripttype="text/javascript">
   1:  
   2:
   3:function onCallbackError(error, context)
   4:     {
   5:     }
   6:  
   7:function onBeforeCallback(arg, context)
   8:     {
   9://return false to cancel
  10:     }
  11:  
  12:function onAfterCallback(result, context)
  13:     {
  14:     }
  15:  
</script>

For causing an update, we call its callback function, passing it a parameter and an optional context:

   1: document.getElementById('callback').callback('test', null);

The most important property in CallbackPanel is the server-side event, OnCallback: this is raised whenever the callback function is called:

   1:protectedvoid OnCallback(Object sender, CallbackEventArgs e)
   2: {
   3:this.time.Text = e.Parameter + ": " + DateTime.Now.ToString();
   4: }

This event receives a CallbackEventArgs argument, which is nothing more than:

   1: [Serializable]
   2:publicsealedclass CallbackEventArgs : EventArgs
   3: {
   4:public CallbackEventArgs(String parameter)
   5:     {
   6:this.Parameter = parameter;
   7:     }
   8:  
   9:public String Parameter { get; private set; }
  10: }

And finally, the code for the CallbackPanel itself:

   1:publicclass CallbackPanel : Panel, INamingContainer, ICallbackEventHandler
   2: {
   3:public CallbackPanel()
   4:     {
   5:this.OnAfterCallback = String.Empty;
   6:this.OnBeforeCallback = String.Empty;
   7:this.OnCallbackError = String.Empty;
   8:this.SendAllData = true;
   9:     }
  10:  
  11:publicevent EventHandler<CallbackEventArgs> Callback;
  12:  
  13:     [DefaultValue("")]
  14:public String OnBeforeCallback { get; set; }
  15:  
  16:     [DefaultValue("")]
  17:public String OnAfterCallback { get; set; }
  18:  
  19:     [DefaultValue("")]
  20:public String OnCallbackError { get; set; }
  21:  
  22:     [DefaultValue(true)]
  23:public Boolean SendAllData { get; set; }
  24:  
  25:protectedoverridevoid OnInit(EventArgs e)
  26:     {
  27:         var sm = ScriptManager.GetCurrent(this.Page);
  28:         var reference = this.Page.ClientScript.GetCallbackEventReference(this, "arg", String.Format("function(result, context){{ document.getElementById('{0}').innerHTML = result; {1} }}", this.ClientID, (String.IsNullOrWhiteSpace(this.OnAfterCallback) == false) ? String.Concat(this.OnAfterCallback, "(result, context);") : String.Empty), "context", String.Format("function(error, context){{ {0} }}", ((String.IsNullOrWhiteSpace(this.OnCallbackError) == false) ? String.Concat(this.OnCallbackError, "(error, context)") : String.Empty)), true);
  29:         var script = String.Concat("\ndocument.getElementById('", this.ClientID, "').callback = function(arg, context){", ((this.SendAllData == true) ? "__theFormPostCollection.length = 0; __theFormPostData = '';  WebForm_InitCallback(); " : "__theFormPostCollection.length = 0; __theFormPostData = '';  WebForm_InitCallback(); for (var i = 0; i < __theFormPostCollection.length; ++i) { if (__theFormPostCollection[i].name.indexOf('" + this.UniqueID + "$') == -1) { __theFormPostCollection[i].value = '' } }; "), (String.IsNullOrWhiteSpace(this.OnBeforeCallback) == true ? String.Empty : String.Concat("if (", this.OnBeforeCallback, "(arg, context) === false) return; ")), reference, ";};\n");
  30:  
  31:if (sm != null)
  32:         {
  33:this.Page.ClientScript.RegisterStartupScript(this.GetType(), String.Concat("callback", this.ClientID), String.Format("Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function() {{ {0} }});\n", script), true);
  34:         }
  35:else
  36:         {
  37:this.Page.ClientScript.RegisterStartupScript(this.GetType(), String.Concat("callback", this.ClientID), script, true);
  38:         }
  39:  
  40:base.OnInit(e);
  41:     }
  42:  
  43:protectedvirtualvoid OnCallback(CallbackEventArgs e)
  44:     {
  45:         var handler = this.Callback;
  46:  
  47:if (handler != null)
  48:         {
  49:             handler(this, e);
  50:         }
  51:     }
  52:  
  53:#region ICallbackEventHandler Members
  54:     String ICallbackEventHandler.GetCallbackResult()
  55:     {
  56:         var builder = new StringBuilder();
  57:  
  58:using (var writer = new StringWriter(builder))
  59:using (var htmlWriter = new HtmlTextWriter(writer))
  60:         {
  61:this.Render(new HtmlTextWriter(writer));
  62:  
  63:return (builder.ToString());
  64:         }
  65:     }
  66:  
  67:void ICallbackEventHandler.RaiseCallbackEvent(String eventArgument)
  68:     {
  69:this.OnCallback(new CallbackEventArgs(eventArgument));
  70:     }
  71:#endregion
  72: }

Again, it is implementing ICallbackEventHandler, for client callbacks, but this time it is inheriting from Panel, which is a nice container for other controls. The rest should be self-explanatory, I guess. If you have questions, do send them to me!

As always, hope you like it! Winking smile


Viewing all articles
Browse latest Browse all 404

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>