search
Twitter Rss Feeds
MicrosoftArticlesForumsGroups
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml/Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

Web ProgrammingArticlesForumsGroups
JavaScript
ASP
ASP.NET
Web Services

Non-MicrosoftArticlesForumsGroups
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

DatabasesArticlesForumsGroups
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsGroups
Microsoft Excel
Microsoft Word
Microsoft Powerpoint
Publisher
Money

Operating SystemsArticlesForumsGroups
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsGroups
Share Point
BizTalk
Site Server
Exhange Server
IIS
Transaction Server

Graphic DesignArticlesForumsGroups
Macromedia Flash
Adobe PhotoShop
Microsoft Expression

OtherArticlesForumsGroups
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Reviews
Search Engines
Resumes

 
Build a Custom AutoPostBack
ASP.NET Page Timer ServerControl

By Peter A. Bromberg, Ph.D.
Printer - Friendly Version

Peter Bromberg

A couple of interesting things happened to me at about the same time recently, and that's why you are reading this article. First, I needed to have an efficient way to control the timed reloading or postback on a page that monitors some Windows Services and shows their status. It was conceivable that the user would need to keep the page up in their browser and watch it over a period of time while monitoring the services in order to see if any of them had stopped or started. Second, I finished reading and reviewing "Professional ASP.NET Server Controls" which has an add-on downloadable chapter about encapsulating client-side Javascript in .NET Server Controls.

At first I reasoned that the easy way to handle this would have been to simply insert a Meta Refresh tag, <meta http-equiv="refresh" content="5"> which would automatically reload the page every 5 seconds.

However, all the cool stuff I read in the Wrox book convinced me that if I took a little time and exercised my noodle, I could come up with a much more useful and extensible .NET way to do this. One which might have a programmable event that could be engineered on the server-side.

The result is my "PAB.PgTimer" ServerControl which is available free for all to download at the bottom of this page.

One of the coolest things about the ServerControl architecture is some methods that allow you to emit client-side Javascript. This can be used for a number of things, and you can even author a 100% client - side DHTML control whose Javascript, css and even images are compiled and encapsulated into the ServerControl DLL Assembly as resources.

A common scenario would be for the control to perform a postback, and if the control you are writing doesn't derive from an existing WebControl that already performs this action, you will have to implement it manually.

All we would need is code that creates the Javascript to do a postback in an ASP.NET page which looks like this:

<script language="javascript">
<!--
setTimeout( "__doPostBack('PgTimer1','')", 5000);
// -->
</script>

Fortunately, there is a built - in method , GetPostBackEventReference, that receives a control and a string argument and returns a string with the proper client - side call to perform the postback, which looks like this:

 

<input type="hidden" name="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" value="" />
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform = document.Default;
theform.__EVENTTARGET.value = eventTarget;
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>

The rest is simply practicing how to author ServerControls and wire them up. In this particular case, it's a pretty simple control because it has no visible UI - it's sole purpose in life is to provide an "elapsed" event which can be programmed against to postback the default form on the ASP.NET page. The cool thing about having this in a ServerControl is that the event handler (in this case, ControlID_Elapsed ) is generated in your ASP.NET page in the Designer view by simply double - clicking on the control. This means you can go ahead and "fill it in" to do whatever you want - go get stock prices, etc. and refresh the info on elements on your page, or simply let the postback occur and whatever happens in your Page_Load simply reoccurs.

PgTimer has two classes, PgTimerDesigner, which derives from ControlDesigner, and PgTimer, whcih derives from Control and also inherits the IPostBackEventHandler interface.

Let's take a look at the code in each class:

using System;
using System.IO;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Text;

namespace PAB.PgTimer
{
[ToolboxDataAttribute("<{0}:PgTimer runat=server></{0}:PgTimer>")]
[DefaultEventAttribute("Elapsed")]
[ToolboxBitmapAttribute(typeof(PgTimer), "PAB.PgTimer.PgTimer.bmp")]
[DesignerAttribute("PAB.PgTimer.PgTimerDesigner", "PAB.PgTimer")]
public class PgTimer : Control, IPostBackEventHandler
{
private int intInterval = 5000;
private bool blnEnabled = true;
private bool blnEnableViewState = true;

[CategoryAttribute("PgTimer")]
[BrowsableAttribute(true)]
[DescriptionAttribute("Number of milliseconds PgTimer waits until firing a postback.")]
[BindableAttribute(true)]
public int Interval
{
  get
  {
    return intInterval;
  }

  set
  {
   intInterval = value;
  }
}

[BindableAttribute(true)]
[CategoryAttribute("PgTimer")]
[DescriptionAttribute("Whether PgTimer Control is enabled.")]
[BrowsableAttribute(true)]
public bool Enabled
{
  get
  {
   return blnEnabled;
  }

set
  {
   blnEnabled = value;
  }
}

[BindableAttribute(false)]
[BrowsableAttribute(false)]
public override bool EnableViewState
{
  get
  {
   return blnEnableViewState;
  }

set
  {
   blnEnableViewState = value;
  }
}


public event EventHandler Elapsed;

protected override void OnInit(EventArgs e)
{
}

protected override void Render(HtmlTextWriter output)
{
if (blnEnabled)
 {
/* Create the Javascript postback "setTimeout" Page Timer code:
<script language="javascript">
<!--
setTimeout( "__doPostBack('PgTimer1','')", 5000);
// -->
</script>
*/

   StringBuilder sb = new StringBuilder();
   sb.Append("\n<script language=\"javascript\"> \n <!-- \n setTimeout( \"");
   sb.Append(base.Page.GetPostBackEventReference(this));
   sb.Append("\", ");
   sb.Append(intInterval.ToString());
   sb.Append("); \n // --> \n </script>");
  output.Write(sb.ToString()); 
  }
}


public void RaisePostBackEvent(string eventArgument)
{
  OnElapsed(new EventArgs());
}

public void OnElapsed(EventArgs ea)
{
  if (Elapsed != null)
   {
    Elapsed(this, ea);
   }
}
}

}

The attributes that decorate the class control the designer and default event:

[ToolboxDataAttribute("<{0}:PgTimer runat=server></{0}:PgTimer>")] -- sets the tag when you drop an instance of the control from your toolbox onto your page.


[DefaultEventAttribute("Elapsed")] -- sets the default event for the control (what we can program against)


[ToolboxBitmapAttribute(typeof(PgTimer), "PAB.PgTimer.PgTimer.bmp")] -- sets the icon for the toolbox - bmp must be the same name as the class, and be set as Build Action=Embedded Resource


[DesignerAttribute("PAB.PgTimer.PgTimerDesigner", "PAB.PgTimer")]
-- sets the designer class for the control

Aside from the above, the only other really important feature is that we override the Render method of the control to output our custom - generated Javascript.

Now here is the code for the Designer Class, which derives from ControlDesigner:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web.UI.Design;

namespace PAB.PgTimer
{
class PgTimerDesigner : ControlDesigner
{
  private PgTimer pgtimer ;
  public override string GetDesignTimeHtml()
{
  return "<label id=\'Lbl1\' style=\'align: center; COLOR:Blue; valign: middle; background-color:FFCC66;    border-width:2px;\' >PgTimer</label>";
}

public override void Initialize(IComponent component)
 {
  pgtimer = (PgTimer)component;
  base.Initialize(component);
   return;

 }
}
}

 

As can be seen, in this simple control which really has no usable UI, all we need to do is override the GetDesignTimeHtml method to show something on the Designer so we can find it when we have dragged an instance from the Toolbox to our page. Everything else is "default" Designer class implementation.

Once this is compiled, all we need to do is choose "Customize Toolbox" by right - clicking on the Toolbox panel when our design view for our web page is active, choose the ".NET Framework Components" tab, and browse to the physical control DLL and bring it in. If you start out with the defaults in the downloaded solution, you'll see our exceptionally innovative "Fried Egg" Eggheadcafe.com icon on your Toolbox as a selectable control item. To add a PgTimer control to a page, just grab the icon from the Toolbox panel and drag - n - drop it on to your page in Design mode! You can then set the only two properties besides the control's ID, which are Enabled and Interval (the number of milliseconds between postback events).

When you double-click on the control, it will expose the Elapsed event handler:

private void PgTimer1_Elapsed(object sender, System.EventArgs e)
{

// do whatever you need to do here (get stock prices, etc.)
}

Note: When you unzip the sample code in the download, there are two folders, PgTimer (for the control project and the solution) and PgTimerTest (for the web project that uses the control). If you unzip this in wwwroot, all you'll need to do is right click on the PgTimerTest folder and choose Web Sharing to make it a virtual directory. I would add in closing that this is the simplest possible implementation, you can add a lot more functionality to this type of control. Enjoy!

Download the code that accompanies this article:

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. Pete's samples at GotDotNet.com have been downloaded over 41,000 times. You can read Peter's UnBlog Here.  --><--NOTE: Post QUESTIONS on FORUMS!

 


Pete's Blog   |    Pete's Resume   |    Robbe's Blog   |    Robbe's Resume   |    Archive #2   |    Archive #3   |    Dotnetslackers   |    XmlPitStop   |    Advertise   |   Contact Us   |   Privacy   |   Copyright (c) 2000 - 2009 eggheadcafe.com  All rights reserved.