Why

I wrote BaseCalendar because I got frustrated with the calendar control that comes with the .NET framework. Even in the latest framework version (4.0) it generates HTML code that cannot be overwritten. For example even if NextPrevFormat is set to CustomText the actual rendered text is wrapped inside a <a href="javascript:doPostBack('...')">...</a> tag. If we want the custom text to be an anchor we end up with nested A tags. Because of this and other non-standard attributes it generates the rendered HTML cannot pass validation. I needed something that would give me full control over the generated HTML and not use or require PostBacks.

Features

  • Full control over the generated HTML. By default it generates HTML tables, but can be easily configured to generate divs, ul/li, or anything else (see demo #4). You can also control how each tag is rendered or if it should be rendered at all.
  • You can change the culture for each individual calendar. (see demo #5)
  • Designed with client-side / Javascript in mind, for example you can assign IDs to any tag.
  • CSS friendly, easy way to assign CSS classes to most generated tags, or do it manually for all tags.
  • Does not rely on VIEWSTATE or PostBack.

How to use

Download the latest version from the "Downloads" section and unzip the solution. Copy and add the BaseControls project to your solution, add a reference to this project and you're good to go. The BaseCalendar control is part of the BaseControls project (there may be other Base* server-side controls in this project in the future). The downloaded file comes with 5 demos.

Architecture

The generated HTML has the following structure:

<calendar>
  <caption />
  <header>
    <navigation />
    <dayofweek />
  </header>  
  <body>
    <row>
      <cell />
      <cell />
      ...
    </row>
    <row>
      ...
    </row>
    ...
  </body>
</calendar>

By default <calendar> will be generated as TABLE, <header> as THEAD, <row> as TR, and so on. Each of these blocks has an event associated, for example <calendar> has the OnRenderMain event, <navigation> has OnRenderHeaderNavigation and so on.

All of these OnRender* events are passed either a BaseTag or BaseTagContent instance. There are a few customized BaseTagContent like BaseTagContentDayOfWeek, but they are basically BaseTagContent instances. The main difference between BaseTag and BaseTagContent is that BaseTagContent can have inner content while BaseTag cannot.

The order of operation for all these events goes something like this:
  • The control creates a tag control (BaseTag or BaseTagContent) and initializes it with the default values.
  • If there is an event handler assigned it gives you an opportunity to make changes to the tag control.
  • Renders the result.
So you have the final saying as to what is generated. You can change the Tag property and output LI instead of TR or to null to not render it at all, add an ID or CSS class, set custom style attributes, or add custom attributes. You also have a way of doing a custom opening / closing tag. Using this technique you can even include two completely separate ending tags (see Demo #4 where we need to add an extra tag with clear:both). If the event passes a BaseTagControl you also have the option of changing the entire content of the tag.

There are a number of CSS attributes that you can use to assign CSS classes. For example there's a CssBodyDay you can use to assign to every day cell, or CssBodyDayWeekend only for weekend days. In cases where more than one class is assigned to a tag the generated HTML will look like <tag class="first second third" />. Of course all this can be overwritten inside the appropriate OnRender* event by removing the class from the tag.Class collection.

Contact

If you have any questions / suggestions / bugs / critiques don't hesitate to contact me. Also, if you end up using the control, I would love to know where you used it.

Last edited Jun 9, 2010 at 4:32 AM by pzolja, version 33