Tuesday, March 9, 2010

Using JQuery for Mouseover, Mouseout and Click on Gridview in ASP.Net

So I have searched, re-searched (pun intended) to find an acceptable solution where I am able to do the following,

1. Enable mouseover and mouseout on a Data Grid View control in ASP.Net
2. Enable Multiple Clickable rows and Single click rows on a grid view control.
3. And access a key data from the row that has been clicked.

Now instead of writing server side code and attaching a ton of javascript at each row creation along with a lot of data, I finally did something with JQuery and Javascript. It works like a charm. Ofcourse, you can all tinker with the code and make the code better... so let me know how it all went!

For starters, here is what you will need..

The latest version of JQuery.

So let's get our hands dirty. (I am obviously assuming you have a test page, with a gridview control on it and a web project created... if not please do that, else reading this would be pointless... ;-D)


STEP1


1. Create a stylesheet and name it.. I dont know, name it something.. maybe styles.css
2. Add the following items to it. This is what we will use to style our grid view. Ofcourse you can use your own styles. The key thing to remember is to have a Pager class if you have paging setup for your grid and a style for tag so that the header is styled too. The pager is important.

.GridClass

{

background-color: #fff;

margin: 5px 0 10px 0;

border: solid 1px #525252;

border-collapse: collapse;

}

.GridClass a

{

color: #284E98;

}

.GridClass a:visited

{

color: #284E98;

}

.GridClass .GridWrap

{

padding: 2px;

border: solid 1px #c1c1c1;

font-size: xx-small;

color: #284E98;

white-space: normal;

}

.GridClass .GridNoWrap

{

padding: 2px;

border: solid 1px #c1c1c1;

font-size: xx-small;

color: #284E98;

white-space: nowrap;

}

.GridClass td

{

padding: 2px;

border: solid 1px #c1c1c1;

font-size: xx-small;

text-align:justify;

color: #284E98;

}

.GridClass th

{

text-align: Center;

padding: 2px 2px 2px 2px;

border-color: #a8bbd5;

border-width: 1px;

border-style: solid;

color: #284E98;

font-size: 8pt;

font-weight: bold;

filter: progid:DXImageTransform.Microsoft.Gradient(endColorstr='#7795BD', startColorstr='#c9d5e4', gradientType='0');

}

.GridClass .alt

{

background: white;

}

.GridClass .pager

{

background: #7795BD;

}

.GridClass .pager table

{

margin: 5px 0;

}

.GridClass .pager td

{

text-align: left;

border-width: 0;

padding: 0 6px;

border-left: solid 1px #666;

font-weight: bold;

color: #fff;

line-height: 12px;

}

.GridClass .pager a

{

color: Black;

text-decoration: none;

}

.GridClass .pager a:hover

{

color: White;

text-decoration: none;

}

.GridClass .pager a:visited

{

color: Black;

text-decoration: none;

}

.GridRowClicked

{

cursor: hand;

}

.GridRowClicked td

{

background-color:#FFFF99;

}

STEP2

Save your stylesheet and create a new file and name it HoverScript.js. We will add our JQuery and Javascripts here and add the following code into the HoverScript.js file and save it.


var PrevRow; //Stores the last clicked row

var NewRow; //Gets the new row clicked

var RowClickedValue = ''; //Stores a comma separated value of the items clicked

var CurrentRowClicked = ''; //Gets the value of the row that has been clicked

var GridPlainHover = '#add8e6'; //Some styling

var GridPlainClicked = '#ffff99'; //Some styling

var GridPlainNeutral = 'white'; //Some styling

var sSkipHeaderFooter = ''; //Tracks whether the Header and Footer will be skipped

var CancelClick = false;

var hdnClickedValues = '';

//This is the function that will set all the hover and click functions.

//The function takes the ClientID of the grid for which the rules will be set

//boolean flags to say if Mulitple clicks should be allowed, If a Header is

//included in the Grid and if a footer is included in the grid. We dont want

//to hover over the Header and footer.

function fn_SetHoverRules(sGrid, bMultiClick, bIncludeHeader, bIncludeFooter) {

if (bIncludeHeader) {

sSkipHeaderFooter = ":first,";

}

if (bIncludeFooter) {

sSkipHeaderFooter = sSkipHeaderFooter + ":last";

}

if (bMultiClick) {

if (sSkipHeaderFooter.length > 0) {

$('table#' + sGrid + ' tr').not(sSkipHeaderFooter).click(function() { fn_RowClickMultiple($(this)) });

}

else

$('table#' + sGrid + ' tr').click(function() { fn_RowClickMultiple($(this)) });

}

else {

if (sSkipHeaderFooter.length > 0) {

$('table#' + sGrid + ' tr').not(sSkipHeaderFooter).click(function() { fn_RowClickSingle($(this)) });

}

else

$('table#' + sGrid + ' tr').click(function() { fn_RowClickSingle($(this)) });

}

if (sSkipHeaderFooter.length > 0) {

$('table#' + sGrid + ' tr').not(sSkipHeaderFooter).mouseover(function() { fn_mouseoverAll($(this)); });

$('table#' + sGrid + ' tr').not(sSkipHeaderFooter).mouseout(function() { fn_mouseoutAll($(this)); });

}

else {

$('table#' + sGrid + ' tr').mouseover(function() { fn_mouseoverAll($(this)); });

$('table#' + sGrid + ' tr').mouseout(function() { fn_mouseoutAll($(this)); });

}

}

function fn_mouseoutAll(item) {

if (item[0].className != 'pager') {

item[0].style.cursor = 'hand';

if (item[0].className != 'GridRowClicked')

item[0].style.backgroundColor = GridPlainNeutral;

}

}

function fn_mouseoverAll(item) {

if (item[0].className != 'pager') {

item[0].style.cursor = 'hand';

if (item[0].className != 'GridRowClicked')

item[0].style.backgroundColor = GridPlainHover;

}

}

function fn_RowClickMultiple(item) {

if (!CancelClick) {

if (item[0].className != 'pager') {

CurrentRowClicked = item[0].cells[0].getAttribute('id');

if (CurrentRowClicked != '') {

if (item[0].className == 'GridRowClicked') {

fn_RemoveKeys(item[0].cells[0].getAttribute('id'));

item[0].className = '';

}

else {

item[0].className = 'GridRowClicked';

fn_AddKeys(item[0].cells[0].getAttribute('id'));

}

}

}

}

CancelClick = false;

} //End fn_RowClickMultiple

function fn_RowClickSingle(item) {

if (!CancelClick) {

if (item[0].className != 'pager') {

RowClickedValue = item[0].cells[0].getAttribute('id');

if (RowClickedValue != '') {

PrevRow = NewRow;

NewRow = item[0];

if (PrevRow != undefined) {

PrevRow.className = '';

PrevRow.style.backgroundColor = GridPlainNeutral;

}

NewRow.style.backgroundColor = GridPlainClicked;

CurrentRowClicked = RowClickedValue;

}

}

}

CancelClick = false;

} //End fn_RowClickSingle

function fn_AddKeys(KeyValue) {

RowClickedValue = RowClickedValue + KeyValue + ';'

}

function fn_RemoveKeys(KeyValue) {

var indexOf = 0;

indexOf = RowClickedValue.indexOf(KeyValue);

if (indexOf >= 0)

RowClickedValue = RowClickedValue.replace(KeyValue + ';', '');

}


STEP 3


In my example, I am using a Gridview control with paging setup. For the purpose of explaining how to do the setup, I have my gridview retrieving information from an Employees table. The key item I will be associating with the Row Click is the “Employee ID” which I will use to perform the required operations. For example, select Multiple Employee rows and click Delete or Select Multiple Employee rows and click a Process button .etc.

Obviously, you will have your own Gridview control with your own Bound or unbound columns. So feel free to modify it the way you want. A few things to remember (and I take the liberty in the assumption)..

  1. The Gridview will have a CSS class as “GridClass”.
  2. If there is a pager, it’s class will be set to “pager” CSS class.
  3. The unique id for each row will be associated with the FIRST VISIBLE COLUMN. Now this is important. For the code above to work correctly, it is assuming that the first visible column of the grid has the id that will be retrieved and stored when the user clicks on the row. If you ommit this step, the javascript will fail to retrieve the id. You can modify that piece get it from whichever column you set the unique key to.

Based on these conditions and assumptions, add a Gridview to your aspx page



<asp:GridView ID="gdvEmployees" runat="server" AutoGenerateColumns="False" AllowPaging="True"

EnableViewState="False" PageSize="500" PagerStyle-CssClass="pager" Width="100%"

AlternatingRowStyle-CssClass="alt" CssClass="GridClass" AllowSorting="True" DataKeyNames="Emp_ID">

<Columns>

<asp:BoundField Visible="false" DataField="Emp_ID" HeaderText="Employee ID"/>

<asp:BoundField DataField="Date_Inserted" HeaderText="Date Inserted" />

<asp:BoundField DataField="Emp_Name" HeaderText="Employee Name"/>

<asp:BoundField DataField="Emp_DOB" HeaderText="Date Of Birth" />

<asp:BoundField DataField="Manager_ID" HeaderText="Manager"/>

Columns>

<PagerStyle CssClass="pager">PagerStyle>

asp:GridView>

Add a hidden control to the page and call it “hdnClickedValues” and enable it to run at Server

<input type="hidden" runat="server" id="hdnClickedValues" value="" />


Add a button to the page that will process the values clicked on the grid.



<asp:Button runat="server" ID="btnShowClicked" Text="Show Clicked" CssClass="ButtonMain"

Width="150px" OnClientClick="return fn_GetValues();" />



I am not going to add the code to retrieve the data from the database and bind it to the grid. You do that. Now once you have done that in your code behind, go to the RowDataBound event of the Gridview and add the following lines of code.



Private Sub gdvEmployees_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gdvUnknownErrors.RowDataBound

'Get the current instance of the Row being bound

Dim GridRow As GridViewRow = e.Row

'Make sure this is a row and not a Header or a Footer

If GridRow.RowType = DataControlRowType.DataRow Then

'Create an instance of the DatarowView from the DataItem being bound

Dim DRV As DataRowView = CType(e.Row.DataItem, DataRowView)

'Make sure we have a Emp_ID

If Not IsDBNull(DRV("Emp_ID")) Then

'Assign the Id attribute to the first visible column, in our case it will be Date Inserted

GridRow.Cells(1).Attributes.Add("id", DRV("Emp_ID"))

End If

End If

End Sub



Now in your aspx source code include the Javascript file and the Style sheet




<script language="javascript" src="/HoverScript.js" type="text/javascript">script>



Just below the include line, add the following script



<script language="javascript" type="text/javascript">

$(document).ready(function() {

var bEnableMultiRowClick = 1; //Set the value to state whether multiple rows can be clicked 1=true, 0=single row click only

var bHasHeader = 1; //Set the value to indicate if the Grid contains a Header 1=Yes, 0=No

var bHasFooter = 1; //Set the value to indicate if the Grid contains a Footer 1=Yes, 0=No

var stblUnknownErrors = '';

stblEmployees = "<%= gdvEmployees.ClientID %>";

hdnClickedValues = "<%= hdnClickedValues.ClientID %>";

fn_SetHoverRules(stblEmployees , bEnableMultiRowClick, bHasHeader, bHasFooter);

});

function fn_GetValues() {

$get(hdnClickedValues).value = RowClickedValue;

return true;

}

script>



In your code behind, add code for the click event of your button control



Protected Sub btnShowClicked_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShowClicked.Click

Dim strClickedRows() As String

Try

strClickedRows = hdnClickedValues.Value.Split(";")

For Each strClickedRow As String In strClickedRows

If Not Trim(strClickedRow) = "" Then

Response.Write(strClickedRow)

End If

Next

LoadGridData(gdvUnknownErrors.PageIndex, "")

Catch ex As Exception

Throw New Exception(ex.Message, ex)

End Try

End Sub



That’s it. Run your web page and see it all come together. I have shown you how you can do the following

  1. Use JQuery to perform Mouse over, Mouse Out and Click on a Grid view control.
  2. Skip Header and Footer from mouse over and mouse out and click while using JQuery to perform that operation.
  3. Retrieve the clicked values in your code behind.

Hope this is helpful to anyone looking for it. I am not including any code for this, it is upto you to put it all together and make it work. Comments are most welcome and I will answer any questions or issues you might have doing this.

No comments:

Post a Comment