GridViewControlExtender - Row MouseOver and Click Styles

In a recent post, I created a GridView that with the help of some JavaScript and CSS rendered similar to the Tablecloth style table shown here.  I like the Tablecloth sample because the presentation of the grid changes as the user interacts it.  It does a good job of keeping the user focused on the data elements the they are currently working with.           

Live Demo (IE6, IE7, FF) | Download  

The design of the Tablecloth grid is fairly simple.  It boils down to adding and removing CSS classes to the individual HTML Table elements (mostly TD's and TH's) in response to a four different DOM events (mouseover, mouseup, mousedown and click).  For example, when the mouse cursor is positioned over a particular cell in the table, the mouseover event fires and a bit of JavaScript runs and applies a CSS class to all of the cells that share the same rowIndex or cellIndex.  The image below shows how this works.  When the mouse is positioned over a particular cell, the .over CSS class is applied to all cells in the same row and column.  In this sample, the same CSS class is applied to all cells, but it wouldn't be too difficult to apply different classes to header or footer cells. 

While looking at the Tablecloth code, I thought it would be useful to incorporate similar features into an AjaxControlToolkit Extender control.  So I created a new GridViewExtenderControl that allows you to specify what CSS classes you want applied to the rows of the GridView when they are hovered on or clicked.  My plan is to implement a couple of simple features, and add on additional functionality after I get the plumbing in place.

For the first version of this new extender control, I implemented the following features:

  • Apply a CSS class to the data rows of the gridview as they are moused-over
  • Apply a CSS class to a selected data row (if you have the demo page open, try click on a data row)

After I created the control, I tested the functionality by extending a couple of my existing grids.  Below are the screenshots, but you can also try them out by viewing the interactive demo.

The markup for the GridViewExtenderControl exposes 3 main attributes:

  1. TargetControlID: The ID of the GridView you want extended
  2. RowHoverCssClass: The Css Class you want applied to the TR elements as they are moused-over
  3. RowSelectedCssClass: the Css Class you want applied to the TR elements as they are clicked on

Here is some sample markup for how this would be used:

<asp:GridView 
    ID="gvTableCloth" runat="server" 
    CssClass="tablecloth-theme" AutoGenerateColumns="false" 
    DataSourceID="odsCustomers" AllowSorting="true">
    <RowStyle CssClass="data-row" />
    <AlternatingRowStyle CssClass="alt-data-row" />
    <Columns>
        <asp:BoundField HeaderText="ID" DataField="customerid" SortExpression="customerid" />
        <asp:BoundField HeaderText="Company" DataField="companyname" SortExpression="companyname" />
        <asp:BoundField HeaderText="Contact" DataField="contactname" SortExpression="contactname" />
        <asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
        <asp:BoundField HeaderText="Country" DataField="country" SortExpression="country" />
    </Columns>
</asp:GridView>
<%-- RowHover is applied to TR's as they are moused-over  --%>
<%-- RowSelect is applied to TR's as they are clicked  --%>
<mb:GridViewControlExtender 
    runat="server" TargetControlID="gvTableCloth" 
    RowHoverCssClass="row-over"
    RowSelectCssClass="row-select" 
/>

And here are the CSS classes for the row-over and row-select classes:

/* mouseover row style */
.tablecloth-theme .row-over { background-color:#ECFBD4; }

/* mouseover row style */
.tablecloth-theme .row-select 
{ 
    background:#BCE774;
    color:#555;
}

Like I said, this is really just the initial draft of this control (and so this posting is tagged as 'Prototype').  But, I am already finding it useful, and I have a feeling that I will be extending it further to include the following features as well ...

  • Use the up and down keyboard arrows to navigate between selected data rows.  The YUI DataTable control does this.  You can play with it here
  • Apply a CSS class to the individual cells of a column that is moused over (to get the veritical highlight effect)
  • Apply a CSS class to the header and footer cells when a cell is moused over.  This would be a nice way to highlight the column a cell belongs to by just changing the style of the header cell, but not all of the other data cell in the column.
  • Apply a CSS class when the mouse-down event fires for a cell.  The Tablecloth grid does this when a header cell is clicked to highlight the column.

The complete source is included in the download.  Feel free to take a look and send me your feedback.  The complete JavaScript file non-minified is only 130 LOC, so hopefully it isn't too intimidating.

That's it.  Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/80

Comments


Posted by: Vish on October 24, 2007 12:00 AM

Thanks a lot.

You always write a article, that is required in a real world programming.

Count on me as one who will visit your site once a day.

Posted by: kosta on October 24, 2007 12:00 AM

Thanks Matt for another great article! It would be great if click would cause (optional) callback with row information (RowClickEventArgs or something like that) and also double click feature would be greatly appreciated.

Thanks alot!

Posted by: Alan Ramsay on November 2, 2007 12:00 AM

Thanks for this. Really useful.

One thing I noticed upon adding this extender to an existing GridView is that you must have values in the CssClass attributes of the RowStyle and AlternatingRowStyle tags. If not then the _IsDataRow function returns false. Rather than change the function I just added in a dummy CssClass value and it all worked fine ;-)

Cheers,
Alan

@Alan -

Good catch. I cant believe I didnt mention this in the post. Because the GridView renders the data rows, footer row and pager row all in tr/tds I couldnt think of a good way to determine what type of row I was looking at. I need this information to determine what CSS class to apply to the row.

Matt.

please how did you get
thanks

Posted by: Jeff Tu on November 27, 2007 12:00 AM

Matt,
It appears to break if there are no rows to display. Also, as Vish had mentioned, it would be great to get a callback when a row has been clicked. Otherwise, this is pretty to look at but does not provide any useful value.

@Jeff Tu -

Good catch. The JavaScript behavior has a chunk of code that gets all of the TR elements from the Table and doesnt correctly check to make sure at least one exists in the first place!

I believe I fixed this problem in my follow up post.

Thanks for pointing this out.

Matt

@Jeff Tu, @Vish -

You guys are right - having the client side click fire the server side row selected event would be a nice addition.

Good feedback. I have put this on the backlog.

Matt.

Posted by: Anu on February 4, 2008 12:00 AM

Hi,

When a CssClass it attached to vever datarow on mouseover, the GridHeaders that are frozen using CssClass starting moving up as you scroll down and comes back to its original position as up scroll up using the mouse. Can you please explain why thi shappens and how to solve this?

Thanks

Posted by: ams on February 10, 2008 12:00 AM

Hi !

I am trying to use the GridViewControlExtender..I have the ASP.NET 2.0 AJAX Extensions installed and i m using Visual Studio 2005. The site is built wit no errors but the gridview rows dont change their row on hover as in the demo...i m missing something?

Please help...

Posted by: DLT on May 24, 2008 12:00 AM

Matt,

Your posts have and will be so helpful to me, I thought I give you a bit of code Ive found useful. It sets the RowStyle based on a value in the DataKeys collection so that rows can be grouped by background color, in this case by household. This code runs in RowDataBound:

// set row colors by Household
// wait until there are two+ rows, then compare current row value to previous row value
if (gvSample.Rows.Count > 1)
{
// rowindex is 0-based vs count which is not, so if count=2, first rowindex is 0, 2nd is 1, etc.
hh1 = int.Parse(gvSample.DataKeys[e.Row.RowIndex - 2].Values["Household"].ToString());
hh2 = int.Parse(gvSample.DataKeys[e.Row.RowIndex - 1].Values["Household"].ToString());
row1 = gvSample.Rows[e.Row.RowIndex - 2];
row2 = gvSample.Rows[e.Row.RowIndex - 1];

if (hh1 == hh2)
{
if (row1.BackColor == gvSample.AlternatingRowStyle.BackColor)
{
row2.BackColor = gvSample.AlternatingRowStyle.BackColor;
}
else
{
row2.BackColor = gvSample.RowStyle.BackColor;
}
}
else
{
if (row1.BackColor == gvSample.AlternatingRowStyle.BackColor)
{
row2.BackColor = gvSample.RowStyle.BackColor;
}
else
{
row2.BackColor = gvSample.AlternatingRowStyle.BackColor;
}
}
}

Posted by: Amrita on June 2, 2008 12:00 AM

The post was really helpful.

I had just one query here, how do I make the first row of the grid as row-select until the user selects any row.

Hope you give a solution sooner.

Thanks a lot,
Amrita

Posted by: Amrita on June 13, 2008 12:00 AM

I got the solution. Thanks

Posted by: Felipe on August 8, 2008 05:11 PM

This extender is great, thanks.

I think that the GridViewControlExtender (GVCE) makes the UpdatePanelAnimationExtender (UPAE) stop working.

When i remeve the GVCE from the page the UPAE works again.

Why would it be ??

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Felipe wrote: This extender is great, thanks. I think that the GridViewControlExtender (GVCE) makes the UpdatePa...
  • Amrita wrote: I got the solution. Thanks ...
  • Amrita wrote: The post was really helpful. I had just one query here, how do I make the first row of the grid as ...
  • DLT wrote: Matt, Your posts have and will be so helpful to me, I thought I give you a bit of code Ive found us...
  • ams wrote: Hi ! I am trying to use the GridViewControlExtender..I have the ASP.NET 2.0 AJAX Extensions install...
  • Anu wrote: Hi, When a CssClass it attached to vever datarow on mouseover, the GridHeaders that are frozen usin...
  • Jeff Tu wrote: Matt, It appears to break if there are no rows to display. Also, as Vish had mentioned, it would b...
  • Matt Berseth wrote: @Jeff Tu - Good catch. The JavaScript behavior has a chunk of code that gets all of the TR elemen...