Tuesday 24 May 2011

Building a Address Book

Building a  Address Book with the List View and LinqDataSource Controls

It has a nice looking address book widget that displays all of your connections partitioned by last name.  To the left of the contact listing is an index that allows you to jump right to a section.  This control isn't overly fancy, but I was curious what HTML/CSS/JavaScript was used to create it.  So I took it apart using the IE Developer Toolbar and rebuilt it using ASP.NET 3.5 - making use primarily of LINQ to XML, the LinqDataSource and a couple of ListView's.  If you are interested in how I created the sample, a quick description of the implementation details can be found just below the screen shot.  And the best part - excluding the CSS.


Creating the LinqDataSource

The demo makes use of a single LinqDataSource that feeds all three ListView controls found on the page.  This datasource returns a record for each of the letters of the alphabet - {A, B, ... Z}.  Additionally, each of these 26 records contains a collection of all of the contacts whose last name starts with the current letter.  If no contacts have last names starting with a given letter, an empty collection is returned.  The table below shows this structure - notice the empty Contacts collection for letters 'C' and 'Z'.  
First Letter of Last Name Contacts
A
FirstName LastName
Syed Abbas
Francois Ajenstat
Alberts Amy
B
FirstName LastName
David Bradley
Kevin Brown
Eric Brown
C
FirstName LastName
... ...
Z
FirstName LastName
To generate this structure, I use LINQ to extract the contact records from an XML file and join them by the first letter of their last name to an in-memory character array that contains all of the letters in the alphabet.  After these structures are joined together, I select out the attributes required to build the interface.  The resulting structure is similar to one that could have been created by grouping the contacts by the first letter of their last name.  I used the join instead because I want to make sure I include all letters - even those that do not have any associated contacts (I use all of the letters to build the index piece of the address book).
image
This LINQ query is wired to a LinqDataSource by placing the code into the datasources Selecting event handler.
image

Contact Listing ListView

After the datasource was created, I moved on to adding the ListView that will generate the listing of contacts for the address book.  The core portion of the address book displays contacts grouped by last name.  I used two ListViews to generate an OL structure for grouping the contacts.  Each of the LI elements within the OL contains a TABLE element that has a row for each contact within the current group.  Before the TABLE element is a H2 element that contains the heading for the current group.  The screen shot below shows how this general structure would be applied to elements listed in the table above. 
image
The outer ListView binds directly to the LinqDataSource we previously created.  This outer ListView generates the grouping information contained within the outer OL element.  Within the ItemTemplate of this ListView is another nested ListView that binds to the Employees property and generates the nested TABLE that contains items for each of the contacts within the current group.
  image

Contact Index ListView

Next, I went ahead and created the markup structure for generating the contact index.  If a letter in the index (like Z or C) does not have any associated contacts, I still want to render the letter.  If there are associated contacts, I want to render an anchor element that will scroll the page automatically to the contacts for the selected index.  Again, I used the ListView to create a OL/LI structure for these items.  If a letter doesn't have any associated contacts, I render the letter within a SPAN.  Otherwise, I render an anchor element and set the href to the ID of the grouping header element I created using the previous ListView.

 image

Some CSS Trickery

The most complex part of the addressbook widget is the CSS that controls how the index and grouping headers are aligned - both accomplish this by making use of negative margins.  The index DIV floats left and has a negative margin set, making sure it displays to the left of the addressbook container. 
image
The 2px solid line that appears before each grouping of contacts is actually the top border of the table (the table is shifted up by setting the top margin to a negative value).  It is shifted up just enough that it aligns with the middle of the H2 element above it.
image

No comments:

Post a Comment