Calendar buggy styles, and the OOP fix!

Note: this entry has moved.

VGA found a recurrent problem most developers and users of the MS Calendar control seem to have, namely, its poor integration with CSS styles. Being an OOP fan, I clearly see an easy way to solve this problem. Inherit Calendar and change its behavior! That's the cool thing about .NET and the new ASP.NET. It's all too easy: 

public class UnStyledCalendar : Calendar { protected override void Render(HtmlTextWriter writer) { base.Render (new NonStyleWriter( writer) ); } }

Cool, huh? The "secret", of course, is the derived writer, which simply implements a passthrough HtmlTextWriter descendant which skips calls to the virtual AddStyleAttribute and WriteStyleAttribute methods:

private class NonStyleWriter : HtmlTextWriter { HtmlTextWriter _writer; public NonStyleWriter(HtmlTextWriter innerWriter) : base(innerWriter.InnerWriter) { _writer = innerWriter; } public override void AddAttribute(HtmlTextWriterAttribute key, string value) { _writer.AddAttribute(key, value); } // Passthrough all other methods public override void AddStyleAttribute(HtmlTextWriterStyle key, string value) { // Do nothing here. We don't want style attributes! } public override void AddStyleAttribute(string name, string value) { // Do nothing here. We don't want style attributes! } public override void WriteStyleAttribute(string name, string value) { // Do nothing here. We don't want style attributes! } public override void WriteStyleAttribute(string name, string value, bool fEncode) { // Do nothing here. We don't want style attributes! } }

What you get is a calendar without ANY style="" attributes whatsoever.
I leave the task of putting this into a library, copying the XSD from the MS Calendar, installing it under the appropriate VS folder to get intellisense, and toolbox item attribute to VGA, which excels in the matter ;). The code can be downloaded from the ASPNET2 Incubator

8 Comments

  • This is a very cool solution ineed :D

    I barly understand what I am doing but if you want to get rid of the cellpadding,spacing,... too then add this





    <xmp>

    public override void AddAttribute(HtmlTextWriterAttribute key, string value)

    {

    //tom

    switch(key.ToString().ToUpper())

    {

    case "ALIGN" : case "CELLPADDING" : case "CELLSPACING" : case "BORDER" :

    break;

    default:

    _writer.AddAttribute(key, value );

    break;

    }



    }

    </xmp>

  • A MUCH better way is to use the HtmlTextWriterAttribute enumeration directly, instead of the string comparison:



    public override void AddAttribute(HtmlTextWriterAttribute key, string value)

    {

    switch (key)

    {

    case HtmlTextWriterAttribute.Align:

    case HtmlTextWriterAttribute.Border:

    case HtmlTextWriterAttribute.Cellpadding:

    case HtmlTextWriterAttribute.Cellspacing:

    return;

    default:

    _writer.AddAttribute(key, value);

    }

    }



    More readable and you can easily add new attributes to ignore.

  • I didn't find a way to access the header and title directly so I hacked it (now this IS a hack ;)).

    You can only set a class on the containing TD.

    But what If you could change January to <span>January</span>? Thats my approach.

    Now I can make those styling guys happy and finaly translate their graphical concept to the .net calendar without compromise.



    Can you find a cleaner way Daniel?



    Dim tel As Integer

    Dim newMonth(12) As String

    Dim newDay(6) As String



    For tel = 0 To 12

    newMonth(tel) = "<span class=CalendarTitleStyleContent>" & Thread.CurrentThread.CurrentCulture.DateTimeFormat.MonthNames(tel) & "</span>"

    Next



    For tel = 0 To 6

    newDay(tel) = "<span class=CalendarHeaderStyleContent>" & Thread.CurrentThread.CurrentCulture.DateTimeFormat.AbbreviatedDayNames(tel) & "</span>"

    Next



    Thread.CurrentThread.CurrentCulture.DateTimeFormat.MonthNames = newMonth

    Thread.CurrentThread.CurrentCulture.DateTimeFormat.YearMonthPattern = "MMMM"

    Thread.CurrentThread.CurrentCulture.DateTimeFormat.AbbreviatedDayNames = newDay

  • I get an error when I try Daniels code :

    Control cannot fall through from one case



    Im not a C# programmer but this worked for me :



    public override void AddAttribute(HtmlTextWriterAttribute key, string value)

    {

    switch (key)

    {

    case HtmlTextWriterAttribute.Align:

    case HtmlTextWriterAttribute.Border:

    case HtmlTextWriterAttribute.Cellpadding:

    case HtmlTextWriterAttribute.Cellspacing:

    break;

    default:

    _writer.AddAttribute(key, value);

    break;

    }

    }

  • Another way to fix it would be to add the break; I forgot below the return statement. My mistake (that's the problem of programming in a TextArea...)

  • I have fixed thecalendar problem by your way but I don't understand why the days still render with a style attribute (color:black)



    ex : <a href="javascript:__doPostBack('Calendario','1598')" style="color:Black">17</a>



    if I want to make the calendar full css I need to fix that too.



    Would you helpme please.



    Pirri.





  • no problem ...



    finaly I fix it with !important css. (it also work fine in Mozilla)



    Just for fun : when are rendered the days ???



    Thanks

    Pirri

  • The days are rendered in the onDaysRenderEvent or something.

    Here you can put your own content instead of the default one.

Comments have been disabled for this content.