Aaron Goldenthal

Sometimes ASP.NET is Rocket Science

A Custom LinkButton for the ASP.NET Calendar

A couple of weeks ago I posted an article on creating a dynamic button in an ASP.NET Calendar.  The one aspect of that solution that wasn’t quite as clean as I would have liked is how the data key for the button that was clicked was determined.  To remedy that, I’ve created a custom server control that inherits from LinkButton, but provides some customization for this particular application.

Specifically, this control:

  • Retains all functionality of the original LinkButton
  • Adds a CalendarClick event that is raised when a button in a Calendar is clicked
  • Within the CalendarClick event, passes the data key of the clicked button in the event args

Nothing really monumental, but I thought it was a good discussion on creating a relatively simple custom server control with a new event and EventArgs.

Step 1 - CalendarClickEventArgs

Building from the bottom up, we’ll first create a class that will provide data for our new event.  In this case, that’s CalendarClickEventArgs.

   1: public class CalendarClickEventArgs : EventArgs
   2: {
   3:     public CalendarClickEventArgs()
   4:     {
   5:     }
   7:     public CalendarClickEventArgs(object dataKey)
   8:     {
   9:         this.DataKey = dataKey;
  10:     }
  12:     public object DataKey { get; set; }
  13: }

This class inherits from EventsArgs, which is the base class for all event argument classes.  There’s one public property, DataKey, that provides the key identifying the button within the Calendar that was clicked, and a couple of constructors.

Step 2 - CalendarClickEventHandler

Next, we’ll create an event handler for our new event.

   1: public delegate void CalendarClickEventHandler (object sender, 
   2:     CalendarClickEventArgs e);

Here we’re simply defining a new delegate with the appropriate signature.  Specifically, a method handling this event should accept an object (the sender), and an instance of CalendarClickEventArgs.

Step 3 - CalendarLinkButton

Finally, we’ll implement the CalendarLinkButtonClass itself.  To start with, we’ll create a class that inherits from LinkButton.

   1: [
   2: DefaultEvent("CalendarClick"), 
   3: ToolboxData("<{0}:CalendarLinkButton runat=\"server\">CalendarLinkButton</{0}:CalendarLinkButton>")
   4: ]
   5: public class CalendarLinkButton : LinkButton
   6: {
   7: }

The DefaultEvent attribute specifies the default event for the control (i.e. the event that’s added if you double click on the control in design view).  The ToolBoxData attribute specifies the markup that’s generated when you add the control from the toolbox.

Next we’ll add an event to raise when the calendar is clicked.  We’re using the Events collection (inherited from control) to hold delegates for the event, which is a pretty standard convention.

   1: public event CalendarClickEventHandler CalendarClick
   2: {
   3:     add
   4:     {
   5:         base.Events.AddHandler(EventCalendarClick, value);
   6:     }
   7:     remove
   8:     {
   9:         base.Events.RemoveHandler(EventCalendarClick, value);
  10:     }
  11: }
  13: private static readonly object EventCalendarClick;

We’ll also define a method to raise the events.  This method will simply call any applicable delegates for this event.

   1: protected virtual void OnCalendarClick(CalendarClickEventArgs e)
   2: {
   3:     CalendarClickEventHandler handler = 
   4:         (CalendarClickEventHandler)base.Events[EventCalendarClick];
   5:     if (handler != null)
   6:     {
   7:         handler(this, e);
   8:     }
   9: }

Finally, we need to implement a mechanism to raise the event.  To accomplish this, we’ll override the RaisePostBackEvent method, which is called by the Page when processing a postback.  Since we want to retain all of the functionality of the original LinkButton, we’ll first call the LinkButton’s RaisePostBackEvent.  This call will:

  • Perform event validation (which includes the event argument, so we get the validation for our Calendar button events)
  • Call the Page.Validate() method if the button causes validation
  • Raise the LinkButton’s Click event
  • Raise the LinkButton’s Command event

After that, we’ll raise our new event – CalendarClick.  Recall from my original post on dynamic buttons in a calendar that the __EVENTARGUMENT form parameter is being used to identify the Calendar button that was clicked.  The CalendarClick event is only raised if an event argument is specified, which should always be true when triggered from the Calendar, but wouldn’t be true if the button itself were clicked.  The Page takes care of pulling __EVENTARGUMENT  and passing it to the RaisePostBackEvent method, so that value is passed to the CalendarClickEventArgs.

   1: protected override void RaisePostBackEvent(string eventArgument)
   2: {
   3:     base.RaisePostBackEvent(eventArgument);
   5:     if (!String.IsNullOrEmpty(eventArgument))
   6:     {
   7:         this.OnCalendarClick(new CalendarClickEventArgs(eventArgument));
   8:     }
   9: }

Below is the complete code for CalendarLinkButton.

   1: [
   2: DefaultEvent("CalendarClick"), 
   3: ToolboxData("<{0}:CalendarLinkButton runat=\"server\">CalendarLinkButton</{0}:CalendarLinkButton>")
   4: ]
   5: public class CalendarLinkButton : LinkButton
   6: {
   7:     protected override void RaisePostBackEvent(string eventArgument)
   8:     {
   9:         base.RaisePostBackEvent(eventArgument);
  11:         if (!String.IsNullOrEmpty(eventArgument))
  12:         {
  13:             this.OnCalendarClick(new CalendarClickEventArgs(eventArgument));
  14:         }
  15:     }
  17:     protected virtual void OnCalendarClick(CalendarClickEventArgs e)
  18:     {
  19:         CalendarClickEventHandler handler = 
  20:             (CalendarClickEventHandler)base.Events[EventCalendarClick];
  21:         if (handler != null)
  22:         {
  23:             handler(this, e);
  24:         }
  25:     }
  27:     public event CalendarClickEventHandler CalendarClick
  28:     {
  29:         add
  30:         {
  31:             base.Events.AddHandler(EventCalendarClick, value);
  32:         }
  33:         remove
  34:         {
  35:             base.Events.RemoveHandler(EventCalendarClick, value);
  36:         }
  37:     }
  39:     private static readonly object EventCalendarClick;
  40: }

That’s all there is to the code, which can be downloaded with the example from my original post.  It also includes a sample page with the required changes (which overall are pretty minor).

Comments (2) -

  • Mickey

    5/11/2009 1:33:22 AM |

    Thanks... This will be a good place for me to start with my calendar. Smile

  • fraude urssaf

    5/7/2012 9:09:02 PM |


Pingbacks and trackbacks (4)+

Comments are closed