<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blog.csp.uwa.edu.au/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Adam's Blog : validation</title><link>http://blog.csp.uwa.edu.au/adam/archive/tags/validation/default.aspx</link><description>Tags: validation</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.2)</generator><item><title>Enhanced Calendar with Next/Previous Year Buttons</title><link>http://blog.csp.uwa.edu.au/adam/archive/2007/02/11/enhanced-calendar-with-next-previous-year-buttons.aspx</link><pubDate>Sun, 11 Feb 2007 01:14:00 GMT</pubDate><guid isPermaLink="false">06c7d2c2-7ef8-4788-b25e-93d668b21aa2:20</guid><dc:creator>adam.n</dc:creator><slash:comments>1</slash:comments><comments>http://blog.csp.uwa.edu.au/adam/comments/20.aspx</comments><wfw:commentRss>http://blog.csp.uwa.edu.au/adam/commentrss.aspx?PostID=20</wfw:commentRss><description>
&lt;p&gt;By default, Visual Studio 2005 includes a useful range of components for building ASP.NET web applications. Unfortunately these components are usually very basic and have restricted usability, but with a small amount of customisation become highly usable.&lt;/p&gt;

&lt;p&gt;Enter the world of User Controls. A User Control uses regular ASP.NET components as building blocks to construct a more complex control that can be used in the same way as a regular component. User Controls can be assigned their own methods, properties, events, and be drag-and-dropped into ASP pages.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;In this post we will create a User Control that enhances the functionality of the basic Calendar control. We are going to adding buttons that go back and forward 1 year. Clearly when for browsing to dates many years ago or in the future, a simple next/previous month button is not sufficient. To select a date 5 years ago, 5 * 12 = 60 clicks would be required. With the successful implimentation of next and previous year buttons, this could be reduced to 5 clicks. A big win for usability. However, the challange here is where to locate our extra buttons within the user control to achieve a seamless layout. Overriding the Render(HtmlTextWriter) method will allow us to get the best result.&lt;br&gt; &lt;/p&gt;

&lt;p&gt;Also, we will add a nullable SelectedDate property. The SelectedDate property of the standard Calendar must be assigned a value, which means it is difficult to have no selected date. As our SelectedDate can take on a null value (representing no selected date), a simple null check can be used to determine if a date has been selected by the user. As a result of this, form validation just became a whole lot simplier.&lt;/p&gt;

&lt;p&gt;Both the .ascx and .ascx.cs sample code files have been included with this post. Feel free to use these as a basis for adding other enhancements to the standard calendar, or even to start development of your own User Controls.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;First we need to create a new User Control for our enhanced calendar (I suggest creating a new folder called CustomControls and putting it in here). So right click on the destination of the control, select 'Add New Item', choose a Web User Control, and name it EnhancedCalendar. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.arach.com.au/%7Evoneuman/pictures/enhancedcalendar/snap01.png" title="Creating the new User Control 1" alt="Creating the new User Control 1" height="125" width="266"&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.arach.com.au/%7Evoneuman/pictures/enhancedcalendar/snap02.png" title="Creating the new User Control 2" alt="Creating the new User Control 2" height="452" width="679"&gt;&lt;/p&gt;

&lt;p&gt;Now we are presented with a blank canvas that is our User Control. From the toolbox, drag over one Calendar control and two link button controls, and give these controls useful names (I have used calDate for the Calendar, btnPrevYear and btnNextYear for the buttons). Change the text for btnPrevYear to "&amp;lt;&amp;lt;"&amp;nbsp; and btnNextYear to "&amp;gt;&amp;gt;" and set both buttons to invisible (as we don't want them to render here). To match the existing interface of the calendar, I gave the buttons a tooltip which describes their function. To handle the selection of a date on calDate, give calDate a SelectionChanged event handler. Finally, give each of the buttons a Click event handler.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.arach.com.au/%7Evoneuman/pictures/enhancedcalendar/snap03.png" title="Design view of the enhanced calendar" alt="Design view of the enhanced calendar" border="1" height="234" width="246"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;That is all we need to do from a design point of view, now we move on to the code behind the scenes. Firstly create a property called SelectedDate, which will allow us to set and
get the date represented by our enhanced calendar. I have chosen SelectedDate to be of
type DateTime? (? makes it nullable) as the standard DateTime type is stored
internally as a primative and thus is not nullable. For the button click event handlers, add or subtract one year from calDate.VisibleDate. Inside the calDate_SelectionChanged handler, we want to update our SelectedDate property with the latest value of calDate.SelectedDate. To be thorough, we should add a method to reset the date on our enhanced calendar, which I have called ResetDate().&lt;/p&gt;

&lt;p&gt;Next we need to alter how our user control is rendered. The procedure we are going to use will follow this basic flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Render calDate to html and store in a string.&lt;/li&gt;

&lt;li&gt;Find the previous month link in the html string, and render btnPrevYear before it.&lt;/li&gt;

&lt;li&gt;Find the next month link in the html string, and render btnNextYear after it.&lt;/li&gt;

&lt;li&gt;Write this string as the html for our user control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;The very first thing we need is a way of getting the rendered html code for a control. In our situation we want the html code for calDate. For this we will write a method called RenderToString(Control), which will render a control to html (regardless of its visibility). In theory this method should belong in a utility class, but for this example I have included it in our enhanced calendar's code.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The next things we need are two Regular Expressions that we can use to identify the next and previous month buttons in the stanrdard calendar's html code. By examining the html code of the standard calendar, the previous month button can be isolated by looking for a hyperlink with enclosed text of &amp;amp;lt;, and similarly the next month button by a hyperlink with enclosed text of &amp;amp;gt;. Once the regular expressions have been written, some static Regex objects are constructed to handle the matching.&lt;/p&gt;

&lt;p&gt;Now that we can identify the previous/next month links and render a control to html, we have all the tools required to insert our next/previous year buttons inside calDate. To perform the inserting we use a MatchEvaluator, which works by calling a target method when ever the Regex object finds a match. We will need to make the target method replace the next/previous month html with the next/previous month html concatenated with the rendered next/previous year button. Of course, two different methods are required; one for the next year and one for the previous year, as the order of the buttons is different. I have called these methods AppendPrevYear and AppendNextYear.&lt;/p&gt;

&lt;p&gt;Finally, all that is left to do is perform these steps in the overrided Render(HtmlTextWriter) method. First render calDate to a string, then insert the previous year year button, then insert the next year button, and then write the final html to the writer. And there you have it, that is all the code required to make our enhanced calendar.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.arach.com.au/%7Evoneuman/pictures/enhancedcalendar/snap04.png" title="Original Calendar vs. Enhanced Calendar" alt="Original Calendar vs. Enhanced Calendar" height="253" width="505"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;With these minor modifications, we now have a more usable (for both developer and end user) calendar control that can be used in the same way as the original. Additionally, it conforms to the same clean and uncluttered layout as the original calendar, which is a bonus. The addition of the next/previous year buttons make this control suitable (when combined with an ajax popup control extender for example) for use as a date selector input for a form. Also, the nullable SelectedDate means that validation of empty required date inputs can occur easily.&lt;/p&gt;

&lt;p&gt;For those readers who want to take this example further, some possible avenues for future development include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expanded the regular expressions to collect the style attribute of the next/previous month hyperlink, and this could also be applied to the next/previous year buttons. This removes the need to synchronise style at compile time, with it instead occuring at run time.&lt;/li&gt;

&lt;li&gt;add a method to the control specifically designed for use with a custom required field validator.&lt;/li&gt;

&lt;li&gt;add more properties that set style attributes of calDate, so style information is not stored in the custom control, and this allow the same control to be used across multiple application.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://blog.csp.uwa.edu.au/aggbug.aspx?PostID=20" width="1" height="1"&gt;</description><enclosure url="http://blog.csp.uwa.edu.au/adam/attachment/20.ashx" length="2056" type="application/zip" /><category domain="http://blog.csp.uwa.edu.au/adam/archive/tags/next+year/default.aspx">next year</category><category domain="http://blog.csp.uwa.edu.au/adam/archive/tags/validation/default.aspx">validation</category><category domain="http://blog.csp.uwa.edu.au/adam/archive/tags/user+control/default.aspx">user control</category><category domain="http://blog.csp.uwa.edu.au/adam/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://blog.csp.uwa.edu.au/adam/archive/tags/enhanced+calendar/default.aspx">enhanced calendar</category></item></channel></rss>