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 02:02 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 05:51 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 10:46 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 can't believe I didn't mention this in the post. Because the GridView renders the data rows, footer row and pager row all in tr/td's I couldn't 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 04:53 PM

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 doesn't 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 04:09 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 06:20 PM

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 10:39 PM

Matt,

Your posts have and will be so helpful to me, I thought I give you a bit of code I've 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 06:05 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 04:52 AM

I got the solution. Thanks

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.)

Sponsor

Recent Comments

  • 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 I've found u...
  • ams wrote: Hi ! I am trying to use the GridViewControlExtender..I have the ASP.NET 2.0 AJAX Extensions insta...
  • Anu wrote: Hi, When a CssClass it attached to vever datarow on mouseover, the GridHeaders that are frozen us...
  • Matt Berseth wrote: @Jeff Tu, @Vish - You guys are right - having the client side click fire the server side ro...
  • Matt Berseth wrote: @Jeff Tu - Good catch. The JavaScript behavior has a chunk of code that gets all of the TR...
  • Jeff Tu wrote: Matt, It appears to break if there are no rows to display. Also, as Vish had mentioned, it would ...

Sponsor