A couple of weeks ago, I was working on some client side UI elements on one of my projects.  I was able to apply some things that I have learned recently (some more recently than others).

The problem is that I have a domain object that tracks the selected days of the week.  Currently the object uses a List<DayOfWeek> to manage the selections.  (This is not exactly the most safe thing because a client could set the list to null.  However, that's a different subject.)  What I was looking for was an easy way to initialize all of the check boxes on the client side when the user chose to create a new schedule or modify an existing one.  Also, I need to apply the changes to the check boxes whenever the user committed his changes.

The solution turned out to be fairly straight forward.  Initially, I had multiple check boxes and quickly discovered how cumbersome that would be.  I could only work with the checkboxes on a one-by-one basis.  Though I had never the use for it before, I dug up the ASP.Net CheckBoxList to see if it would meet my needs.  It turned out to be a winner.

The aspx:

    1 <asp:CheckBoxList ID="WeeklyDaysOfWeek" runat="server" RepeatLayout="Flow" RepeatDirection="Horizontal">
    2     <asp:ListItem Text="Mon" Value="Monday"></asp:ListItem>
    3     <asp:ListItem Text="Tue" Value="Tuesday"></asp:ListItem>
    4     <asp:ListItem Text="Wed" Value="Wednesday"></asp:ListItem>
    5     <asp:ListItem Text="Thu" Value="Thursday"></asp:ListItem>
    6     <asp:ListItem Text="Fri" Value="Friday"></asp:ListItem>
    7     <asp:ListItem Text="Sat" Value="Saturday"></asp:ListItem>
    8     <asp:ListItem Text="Sun" Value="Sunday"></asp:ListItem>
    9 </asp:CheckBoxList>


The simplest piece was getting the results from the client to my domain object.  With a little bit of Linq, this was cake:

    1 schedule.ScheduleCriteria.DaysOfWeek = (from ListItem li in WeeklyDaysOfWeek.Items
    2                                         where li.Selected
    3                                         select li.Value.ConvertTo<DayOfWeek>()).ToList();

By the way, ConvertTo is an extension method I wrote for "string" to convert to an Enum. 

Regarding the Linq query, it really simplifies grabbing selected items.  This can be applied to a ListBox with SelectionMode = Multiple as well.  In this case, I am looking at all of the items in the CheckBoxList, grabbing only those that are Selected and converting the Value to an Enum.  Previously, without Linq, we would have had to manually construct a list by manually looping the items and adding selected items to the list.

The next piece is getting the data from the domain object into the UI component.  I had two scenarios.  The first was in the context of creating a new schedule.  In this case, weekdays should be selected by default.  (You could argue that default logic doesn't belong in the UI.  Again, off topic).  The second scenario involved editing an existing schedule.  To enhance usability, I am displaying the "Add/Edit Schedule" dialog with a couple of update panels supported by jQuery.

If the user clicks "Add", then the partial postback results in emitting jQuery statements that update all of the input controls with their defaults.  For the CheckBoxList in particular:

    1 for( int i = 0; i < WeeklyDaysOfWeek.Items.Count; i++ )
    2 {
    3     builder.AppendFormat( "jQuery('#{0} > input:checkbox:eq({1})').attr('checked',{2});",
    4                          WeeklyDaysOfWeek.ClientID,
    5                          i,
    6                          (i < 5) ? "true" : "false" );
    7 }

To explain the jQuery, the selector is grabbing the Nth ("eq") checkbox (":checkbox") child of the WeeklyDaysOfWeek CheckBoxList.  Then, the "checked" attribute of first 5 (Mon-Fri) is checked, and unchecked for the last two (Sat, Sun).
So:
  • "#{0}"  <--  WeeklyDaysOfWeek.ClientID
    To select the parent control by ID
  • " > input:checkbox"
    To select all checkbox children
  • ":eq({1})"  <-- i (the index of the item we care about)
    To select a specific child by index
  • ".attr("checked",{2})  <--  (i < 5) ? "true" : "false"
    To check/uncheck the child
In the case where the user is editing an existing schedule, the loop is basically the same.  The only different is how to determine if each check box should be checked.  In this case, we simply check to see if the list contains the day of week that the check box represents:

    1 for( int i = 0; i < WeeklyDaysOfWeek.Items.Count; i++ )
    2 {
    3     var dow = WeeklyDaysOfWeek.Items[i].Value.ConvertTo<DayOfWeek>();
    4     builder.AppendFormat( "jQuery('#{0} > input:checkbox:eq({1})').attr('checked',{2});",
    5                          WeeklyDaysOfWeek.ClientID,
    6                          i,
    7                          schedule.ScheduleCriteria.DaysOfWeek.Contains( dow ).ToString().ToLower() );
    8 }

Anyway, I was very pleased (especially with the Linq piece) at how the combination of all of these components/tools came together to provide a simple solution to my problem.

Tags: ,
posted on Tuesday, February 17, 2009 12:51 PM
Filed Under [ Linq ASP.Net AJAX jQuery Web Development ]

Comments

No comments posted yet.

Post A Comment
Title:
Name:
Email:
Comment:
Verification: