Introduction
Implementing GridView
rows navigation using arrow (up/down) keys is an easy task in IE but a little tricky in other web browsers. Initially, when I wrote the JavaScript code for it, the script was working well in IE but not in other browsers. After doing lots of R&D on the Internet, I learned some tricks from the Mozilla Development Center web site [^] in order to run this script on other web browsers.
Using this script, you can navigate GridView
rows with the help of the arrow (up/down) keys, but before navigating, you have to select a row using the mouse onclick
event.
HTML Code
Below is the HTML code for the GridView
for this demo:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False"
OnRowCreated="gridView_RowCreated"
TabIndex="0" GridLines="Horizontal">
<Columns>
<asp:BoundField HeaderText="S#" DataField="sno">
<HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="50px" />
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="50px" />
</asp:BoundField>
<asp:BoundField HeaderText="Random No" DataField="rndno">
<HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="150px" />
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="150px" />
</asp:BoundField>
<asp:BoundField HeaderText="Date" DataField="date">
<HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
</asp:BoundField>
<asp:BoundField HeaderText="Time" DataField="time">
<HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
</asp:BoundField>
</Columns>
<RowStyle BackColor="#FFE0C0" />
<HeaderStyle BackColor="#FF8000" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="#FFC080" />
</asp:GridView>
In this demo, the GridView
works like a component with the TabIndex
equal to 0.
C# Code
Below is the C# code of the RowCreated
event of the GridView
:
if (e.Row.RowType == DataControlRowType.DataRow &&
(e.Row.RowState == DataControlRowState.Normal ||
e.Row.RowState == DataControlRowState.Alternate))
{
e.Row.TabIndex = -1;
e.Row.Attributes["onclick"] =
string.Format("javascript:SelectRow(this, {0});", e.Row.RowIndex);
e.Row.Attributes["onkeydown"] = "javascript:return SelectSibling(event);";
e.Row.Attributes["onselectstart"] = "javascript:return false;";
}
In the above code, first, it has been ensured that the row is either Normal
or Alternate
. After that, the client-side events onclick
, onkeydown
, and onselectstart
are attached on each of the rows of the GirdView
. Also, note that each row of the GirdView
has been set to have a TabIndex
equal to -1 in order to set the focus on it programmatically. Actually, in this example, the GridView
works like a component with TabIndex
= 0, and each row of the GridView
behaves like an element of the component with TabIndex
= -1. Navigation to each element in the component is done via the arrow keys. A row receives focus when the user navigates to it using the arrow (up/down) keys. Arrow key support is achieved by associating the onkeydown
event on each of the rows of the GridView
.
When trapping key events, it is important to prevent the browser from executing the default behavior of the keystroke. The common browser action resulting from a down/up arrow press is to scroll the document. If you wishes to trap the arrow keys and use them to change focus to a different GridView
row, the default scrolling behavior needs to be prevented. This is done by setting the return value equal to false
of the event. Please note how the onkeydown
event has been attached on the row.
The onclick
event is used here to select a row using the mouse. Before navigating a GridView
’s rows using the arrow (up/down) keys, we have to select a row using the mouse onclick
event.
The onselectstart
event is used here to prevent cell text highlighting when selecting GridView
rows using the mouse.
JavaScript Code
<script type="text/javascript">
var SelectedRow = null;
var SelectedRowIndex = null;
var UpperBound = null;
var LowerBound = null;
window.onload = function()
{
UpperBound = parseInt('<%= this.gridView.Rows.Count %>') - 1;
LowerBound = 0;
SelectedRowIndex = -1;
}
function SelectRow(CurrentRow, RowIndex)
{
if(SelectedRow == CurrentRow || RowIndex > UpperBound || RowIndex < LowerBound)
return;
if(SelectedRow != null)
{
SelectedRow.style.backgroundColor = SelectedRow.originalBackgroundColor;
SelectedRow.style.color = SelectedRow.originalForeColor;
}
if(CurrentRow != null)
{
CurrentRow.originalBackgroundColor = CurrentRow.style.backgroundColor;
CurrentRow.originalForeColor = CurrentRow.style.color;
CurrentRow.style.backgroundColor = '#DCFC5C';
CurrentRow.style.color = 'Black';
}
SelectedRow = CurrentRow;
SelectedRowIndex = RowIndex;
setTimeout("SelectedRow.focus();",0);
}
function SelectSibling(e)
{
var e = e ? e : window.event;
var KeyCode = e.which ? e.which : e.keyCode;
if(KeyCode == 40)
SelectRow(SelectedRow.nextSibling, SelectedRowIndex + 1);
else if(KeyCode == 38)
SelectRow(SelectedRow.previousSibling, SelectedRowIndex - 1);
return false;
}
</script>
In the above script, the global variables have been initialized in the window.onload
event. There are two functions: SelectRow
and SelectSibling
. SelectRow
is invoked when we click on a GridView
row, or via the SelectSibling
method in response to keydown
or keyup
events. The SelectSibling
method is invoked when we press the up or down arrow key. This method invokes the SelectRow
method with appropriate arguments. In the SelectRow
function, if the current row is the previous selected row or RowIndex
is not in between LowerBound
and UpperBound
, it doesn’t do any action; otherwise, it restores the previous selected row’s state and changes the state of the current selected row. After that, the values of the variables SelectedRow
and SelectedRowIndex
are changed accordingly and the focus on the currently selected row is set using the setTimeout
method. The timeout is necessary in both IE and Mozilla, to prevent scripts from doing strange unexpected things as the user clicks on buttons and other controls.
Conclusion
I have tried my best to make this code error free. Suggestions and criticism for further improvements of this code are most welcome.
Browser Compatibility
I have tested this code on various browsers and it worked fine. The list of browsers along with versions is given below:
This code will not work currently on Opera (earlier version of 9.27), Safari, Firebox (as of 1.0), and older versions of Mozilla (1.7 and earlier) as some browsers don’t support the new capabilities like the TabIndex
property on all elements.